Thanks in advance for your feedback. I can't make sense of an ArrayIndexOutofBoundsException error in the snippet of code below. Is it obvious to any of you?
public void run() {
int x = 10;
int y = 10;
double[][] Lx = new double[x][y];
double[][] Ly = new double[x][y];
for (int i=0; i<Lx.length; i++) {
for (int j=0; j<Lx[0].length; i++) {
Lx[j][i] = 2*j+i-1;
Ly[j][i] = Math.sqrt(3)*(i-1);
}
}
}
Your j for loop is incorrect in incrementing i, not j. Change
for (int j=0; j<Lx[0].length; i++) {
to
for (int j=0; j<Lx[0].length; j++) {
In addition, your array access indices are backwards. Change
Lx[j][i]
to
Lx[i][j]
and likewise with Ly. Otherwise you'll get a flipped 2D array.
With addition to #rgettman's answer
As in here your x and y is same so you will not have any issue with Lx[0].length. But it is good to use Lx[i].length.
Lx[0].length will always give the length or number of columns present in the 0th row. But Lx[i].length will give the length or number of columns present in the ith row.
So in case your x and y differs you will not again get ArrayIndexOutBoundException.
It should be j++ not i++ in the nested for-loop.
It's better not to use i and j for the index because they look too similar.
i and k are much more distinct than i and j
Related
I started to read the famous "cracking the Coding Interview" book and I want to do the following exercice.
Write an algorithm such that if an element in an MxN matrix is 0, its entire row and column is set to 0.
Here is the author's solution :
public static void setZeros(int[][] matrix) {
int[] row = new int[matrix.length];
int[] column = new int[matrix[0].length];
// Store the row and column index with value 0
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length;j++) {
if (matrix[i][j] == 0) {
row[i] = 1;
column[j] = 1;
}
}
}
// Set arr[i][j] to 0 if either row i or column j has a 0
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
if ((row[i] == 1 || column[j] == 1)) {
matrix[i][j] = 0;
}
}
}
}
I agree with the author about the main idea. We don't have to store the position of '0' in the matrix but only the position of the rows and columns that are concernerd. But what I found a little "strange" in her solution is that at the end, she did a loop on all the cells of the matrix, which is not necessary in my opinion.
Here is my solution :
static int[][] replaceMatrix(int[][] matrix){
int M = matrix.length;
int N = matrix[0].length;
boolean[] row = new boolean[M] ;
boolean[] column = new boolean[N];
for (int i =0; i< M; i++) {
for (int j = 0; j<N; j++ ){
if (matrix[i][j] == 0) {
row[i] = true;
column[j] = true;
}
}
}
for (int i =0; i<M; i++){
if (row[i]){
for (int k =0; k<N; k++){
matrix[i][k]=0;
}
}
}
for (int j =0; j<N; j++){
if (column[j]){
for (int k =0; k<M; k++){
matrix[k][j]=0;
}
}
}
I'am newbie in programmation so I'm not totaly sure about this. But in my solution, if we except the first step which is to store the 0 positions, my second part of my programme have a time complexity of O(M+N) while her solution has a complexity of O(M*N).
The problem is that the general complexity will be the same O(M*N + (M+N)) is the same that having the complexity O(2*M*N), no? (I'm not totally sure).
For example, if it's a matrix with M=N, so the two complexity of the two programs will be O(M^2).
I really want to know if there is a difference or not about complexity in this case?
ps : I read that the space complexity can be improved with a bit vector. But I really didn't understand. Can you just give me a general idea about it (in Java)?
Time complexity of your last two for loops is still O(M*N) as in worst case inner for loop will be running maximum value of k times.
There is technically no difference in your and the author's solution because both of you have traversed the entire matrix.So both codes are same ** if we have to consider big O notation**
In fact the author's code is a little bit( by little bit I do not mean a different time complexity) better. Here is the reason:
Suppose in your boolean array of rows, all rows are set true. Then in your case you will go through all rows and through each element of every row which is basically traversing the entire matrix.
Suppose in your boolean array of columns, all columns are set true. Then in your case you will go through all columns and through each element of every column which is basically traversing the entire matrix.
So you will in effect traverse the entire matrix twice. But the time complexity of the codes is the same because O(M*N) and O(2*M*N) is same.
You have already done saving space, since you used boolean data type.
A little lost on correct logic to make a subarray using for loops and not using the arrays class.
Cell[][] subArray = new Cell[10][78];
Cell[][] padded = makePaddedArray(message);
for (int i = 0; i < subArray.length; i++) {
for (int j = animationPattern; j < subArray[i].length + animationPattern; j++) {
subArray[i][j - animationPattern] = padded[i][j]; // out of bounds exception here -- column length?
}
}
Where animationPattern is an Integer equal to 1 for the most part and the padded array has the the dimensions [10][ ]. Also a cell is just an object.
I just honestly am looking for some clarification on how to make a subarray work here and the basis behind the out of bounds exception I'm receiving.
EDIT: makePaddedArray returns a 2D cell array with dimensions [10][x], where x is greater than or equal to 165.
Try changing this:
for (int i = 0; i < subArray.length; i++) {
for this:
for (int i = 0; i < subArray.length-1; i++) {
As you start from 0, and not from 1, you need to lower the end of the array also by 1.
I need to have the columns organized in increasing order. Right now I have the following done but, it is sorting the rows and not columns.Any help would be nice, ive been working on this all day. Thanks.
public static double[][] sortColumns(double[][] m) {
double[][] sortedArray = new double[m.length][m.length];
for (int i = 0; i < m.length; i++) {
double[] temp = new double[m.length];
for (int j = 0; j < m.length; j++) {
temp[j] = m[j][i];
}
Arrays.sort(temp);
for (int j = 0; j < temp.length; j++) {
sortedArray[j][i] = temp[j];
}
}
return sortedArray;
}
If you change
temp[j] = m[j][i];
to
temp[j] = m[i][j];
and
sortedArray[j][i] = temp[j];
to
sortedArray[i][j] = temp[j];
then your existing algorithm will work fine. It just means you'll be copying columns to your "temporary sorting area" instead of rows.
In your current solution, you are just mistaking on indexes, just like David Wallace tells you in his answer. I propose you a different answer, enumerating the possible solutions of this problem.
You have at least 4 solutions :
instead of storing your data like you are currently doing it, use the transponate of your matrix
implement yourself an efficient sorting algorithm that takes a bi-dimensional array and the index of a column in argument
at each turn of you loop, fill an array with the current column, sort it, and copy it back (if you don't care about using some additional memory, do it). That is what you are currently trying to do
transponate your matrix, sort its lines, transponate it back (if you don't want to use too much memory, use this)
I prefer the last solution, which code is :
public static double[][] sortColumns(double[][] m) {
double[][] sortedArray = new double[m.length][m.length];
// compute the transponate of m
for (int i=0 ; i<m.length ; i++)
for (int j=0 ; j<m[i].length ; j++)
sortedArray[j][i] = m[i][j];
// sort the lines of the transponate
for (int i=0; i<sortedArray.length; i++)
Arrays.sort(sortedArray[i]);
// transponate back the result of the sorting
for (int i=0 ; i<sortedArray.length ; i++)
for (int j=i+1 ; j<sortedArray[i].length ; j++) {
double tmp = sortedArray[i][j];
sortedArray[i][j] = sortedArray[j][i];
sortedArray[j][i] = tmp;
}
return sortedArray;
}
When I look at your code I see the following line:
double[][] sortedArray = new double[m.length][m.length];
it doesn't look right to me.
you need to find length and breath of the array so i would do something like this:
length = m.length;
breath = m[0].length;
if i m not sure of all rows have same no of elements i may do that check by a for loop and initialize with the max.. wud lead to memory wastage but thats another demon to tame :)
next when we write m[x][y] x represents the rows and y represents the columns so when ur doing :
for (int j = 0; j < m.length; j++) {
temp[j] = m[j][i];
}
Arrays.sort(temp);
you are fetching all the values from a column i, assigning it to temp array and sorting the column.
hope that helps
I'm making a pretty simple java-program and I get the following error (where n is a random number based on previous input from console):
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: n
the line that is supposed to cause trouble is the if-statement here:
for(int i = 0; 0 < x; i++){
if(TalArray[i] < min){
min = TalArray[i];
}
}
the variable "min" is previously initzialized to TalArray[0] and is keeping track of the lowest number. All variables mentioned are int-variables
The correct code is...
for(int i = 0; i < x; i++){
if(TalArray[i] < min){
min = TalArray[i];
}
}
It's not clear what's the value of x in the code, but anyway the loop condition should look like this:
for (int i = 0; i < TalArray.length; i++)
Or like this, to avoid accessing the length at each iteration:
for (int i = 0, x = TalArray.length; i < x; i++)
The 0 < x comparison is mistaken: you're not modifying the value of x inside the loop, so the loop will either enter an infinite loop or not enter the loop at all, depending on the initial value of x.
The problem is, that your variable X is never changing so
your condition 0 < x is always true.
I guess the correct condition would be
for(int i = 0; i < x; i++)
Here's the code:
public class Deck {
private Card[] cards;
public Deck() {
cards = new Card[52];
String[] ranks = {"ace","two","three","four","five","six","seven","eight","nine","ten","jack","queen","king"};
String[] suits = {"hearts","diamonds","clubs","spades"};
for(int i = 0; i < suits.length; i++) {
for(int n = 0; n < ranks.length; n++) {
cards[cards.length] = new Card(ranks[i],suits[n]);
}
}
}
}
As you can see, this loops though the two given arrays and generates a card for every combination. There are 13 ranks x 4 suits = 52 cards. I expected that on the 52nd iteration, cards.length would be 51, but the compiler says
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 52
at com.cards.Deck.<init>(Deck.java:14)
Why is that?
The issue is that cards.length is not the total number of elements used in the array; it's the total number of elements in the array, regardless of what you've stored in the array so far. Consequently, as soon as you execute the inner loop, this will try accessing the 52nd element of the array, causing the exception you've seen.
To fix this, consider instead storing a counter that will keep track of the next free index, or use some simple math to derive the position that the card should go in from its suit and value. For example, since on each iteration of the outer loop you will write ranks.length elements to the array, on iteration (i, n) you will write to array index i * ranks.length + n. Using this, you could rewrite the inner loop as
// Careful... still buggy!
for(int i = 0; i < suits.length; i++) {
for(int n = 0; n < ranks.length; n++) {
cards[i * ranks.length + n] = new Card(ranks[i],suits[n]);
}
}
Additionally, note that your access into the arrays is wrong. Right now, you're writing
new Card(ranks[i],suits[n]);
However, i ranges over suits, not values. The proper code would be
new Card(ranks[n],suits[i]);
Which gives this final implementation:
for(int i = 0; i < suits.length; i++) {
for(int n = 0; n < ranks.length; n++) {
cards[i * ranks.length + n] = new Card(ranks[n],suits[i]);
}
}
More generally, though, don't use the .length field of an array to track how many used elements there are. You'll need to store that separately. Alternatively, consider using an ArrayList, which wraps an array and tracks this for you.
Hope this helps!
cards[cards.length]
Because you're trying to use an index that doesn't exist. cards.length is 52, your array is 0 - 51.
I suspect you're trying to insert each card into that array, which means you need another counter ;)
int cardIndex = 0;
for(int i = 0; i < suits.length; i++) {
for(int n = 0; n < ranks.length; n++, cardIndex++) {
cards[cardIndex] = new Card(ranks[n],suits[i]);
}
}
EDIT: What I didn't catch is what others have mentioned - you also have the counters for ranks/suits switched in the Card constructor - fixed that too.
The index variables for ranks ranks and suits are exchanged.
(Don't damage your head with your palm.)
Consider it with renamed variables:
for(int SUIT = 0; SUIT < suits.length; SUIT++) {
for(int RANK = 0; RANK < ranks.length; RANK++) {
cards[cards.length] = new Card(ranks[SUIT],suits[RANK]);
}
}
It isn't always best to use i and n. (I would have used s and r.)
Also, consider:
Card[] cards = new Card[X];
cards[X] // will never be "in bounds", indices from [0, X-1]
Happy coding.