giovanni ghisellini giovanni ghisellini - 7 months ago 24
Java Question

Java matrix runtime error

Exercise letter:

Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order.

For example, Given the following matrix:

[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
You should return [1,2,3,6,9,8,7,4,5].


Given code:

public class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
}
}


My code:

public List<Integer> spiralOrder(int[][] matrix) {
if(matrix == null || (matrix.length == 0))
return new ArrayList<Integer>();
int arriba = 0;
int derecha = matrix[0].length - 1;
int abajo = matrix.length - 1;
int izquierda = 0;
List<Integer> retorno = new ArrayList<Integer>();
while(true)
{
for(int i = izquierda; i <= derecha; i++)
retorno.add(matrix[arriba][i]);
arriba++;
for(int i = arriba; i <= abajo; i++)
retorno.add(matrix[i][derecha]);
derecha--;
for(int i = derecha; i >= izquierda; i--)
retorno.add(matrix[abajo][i]);
abajo--;
for(int i = abajo; i >= arriba; i--)
retorno.add(matrix[i][izquierda]);
izquierda++;
if(izquierda >= derecha)
return retorno;
}
}
}


The error:

Runtime Error Message:
Line 13: java.lang.ArrayIndexOutOfBoundsException: 1
Last executed input:
[[1,2,3,4,5,6,7,8,9,10]]


Any suggestions? I can't really tell what is wrong. Why is it out of bounds?
Exercise can be found here

Answer

I tried your method with this matrix:

int[][] matrix = {{1,2,3},
                  {2,3,4},
                  {3,4,5}};

and I did not get any ArrayIndexOutOfBoundsException. Your code does not seem to throw any errors.

However, I noticed that the output is not as expected. The output it gave me was 12345432 (only 8 numbers), missing the number 3 in the middle of the matrix.

After having a thorough look at your code I realised that the error lies in if(izquierda >= derecha). If you change this to if(izquierda > derecha) it will not miss the 3. For the same reason you did this, you need to also check for arriba > abajo, otherwise your program does not work for any matrix that has more columns than rows.

Edit: You need these checks after every for-loop.

I suggest you move the return retorno; outside the while-loop, and insert break in the checks:

public List<Integer> spiralOrder(int[][] matrix) {
    if(matrix == null || (matrix.length == 0))
        return new ArrayList<Integer>();
    int arriba = 0;
    int derecha = matrix[0].length - 1;
    int abajo = matrix.length - 1;
    int izquierda = 0;
    List<Integer> retorno = new ArrayList<Integer>();
    while(true)
    {
        for(int i = izquierda; i <= derecha; i++)
            retorno.add(matrix[arriba][i]);
        arriba++;
        if(arriba > abajo)
            break;

        for(int i = arriba; i <= abajo; i++)
             retorno.add(matrix[i][derecha]);
        derecha--;
        if(izquierda > derecha)
            break;

        for(int i = derecha; i >= izquierda; i--)
            retorno.add(matrix[abajo][i]);
        abajo--;
        if(arriba > abajo)
            break;

        for(int i = abajo; i >= arriba; i--)
            retorno.add(matrix[i][izquierda]);
        izquierda++;
        if(izquierda > derecha)
            break;
    }
    return retorno;
}

Side note: It was not easy making sense of izquierda, derecha, arriba, and abajo, since they "move around" in the spiral. But if you think of them as "marking" the non-checked sides of the matrix, you see that izquierda and derecha are both marking down the number 3, but since you have written >=, you ignored it and missed the 3.

Comments