问题
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
回答1:
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;
}
Explanation of your code (by request): Imagine you have a matrix with four persons standing around it - each on one side. These four persons are called arriba
, derecha
, abajo
, and izquierda
:
arriba
1 2 3 4 5
izquierda 2 3 4 5 6 derecha
3 4 5 6 7
abajo
These four people can see the line of numbers right in front of them:
arriba
sees1 2 3 4 5
.derecha
sees5 6 7
.abajo
sees3 4 5 6 7
.izquierda
sees1 2 3
.
Whenever all the numbers in front of any of these persons are added to the list retorno
, they jump forward one step. For example after the first for-loop, it looks like this:
1 2 3 4 5
arriba
izquierda 2 3 4 5 6 derecha
3 4 5 6 7
abajo
After the whole first iteration of the while-loop, they stand like this:
1 2 3 4 5
arriba
2 izquierda 3 4 5 derecha 6
abajo
3 4 5 6 7
arriba
is moving downwards.derecha
is moving to the left.abajo
is moving upwards.izquierda
is moving to the right.
As soon as any of these two persons pass each other, you know that there are no numbers in between them and you need to stop the loop immediately. This is why you need to check if two persons have passed each other every time someone takes a step (after every for-loop).
回答2:
Try this.
static int[][] DIRECTIONS = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
static boolean movable(int r, int c, int height, int width, boolean[][] visited) {
if (r < 0 || r >= height || c < 0 || c >= width)
return false;
return !visited[r][c];
}
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> result = new ArrayList<>();
int height = matrix.length;
if (height == 0) return result;
int width = matrix[0].length;
if (width == 0) return result;
boolean[][] visited = new boolean[height][width];
int direction = 0;
int r = 0, c = 0;
for (int i = 0; i < width * height; ++i) {
result.add(matrix[r][c]);
visited[r][c] = true;
int[] directions = DIRECTIONS[direction % DIRECTIONS.length];
if (!movable(r + directions[0], c + directions[1], height, width, visited))
directions = DIRECTIONS[++direction % DIRECTIONS.length];
r += directions[0];
c += directions[1];
}
return result;
}
来源:https://stackoverflow.com/questions/36706136/java-matrix-runtime-error