问题:
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]
.
解决:
① 没有特别简化的方法,只能一步步的来。如果矩阵只有一行或者一列,那么无需转圈,依次输出即可。其他情况均需转圈:从左到右,从上到下,从右到左,从下到上。 从大圈依次循环到小圈即可。
class Solution { //3ms
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> res = new ArrayList<>();
if(matrix == null || matrix.length == 0 || matrix[0].length == 0) return res;
getSpiral(matrix,0,0,matrix.length,matrix[0].length,res);
return res;
}
public void getSpiral(int[][] matrix,int x,int y,int rows,int cols,List<Integer> res){
if(rows <= 0 || cols <= 0) return;
for (int i = 0;i < cols ;i ++ ) {//由左到右
res.add(matrix[x][y + i]);
}
for (int i = 1;i < rows - 1 ;i ++ ) {//由上到下
res.add(matrix[x + i][y + cols - 1]);
}
if(rows > 1){//由右到左
for (int i = cols - 1;i >= 0 ;i -- ) {
res.add(matrix[x + rows - 1][y + i]);
}
}
if(cols > 1){
for (int i = rows - 2;i > 0 ;i -- ) {//由下到上
res.add(matrix[x + i][y]);
}
}
getSpiral(matrix,x + 1,y + 1,rows - 2,cols - 2,res);
}
}
② 使用top,bottom,right,left记录四个角。可以减少错误。只需要判断四个边界是否相撞即可。
class Solution{ //3ms
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> res = new ArrayList<Integer>();
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return res;
}
int rows = matrix.length;
int cols = matrix[0].length;
int left = 0;
int right = cols - 1;
int top = 0;
int bottom = rows - 1;
while (left <= right && top <= bottom) {
for (int i = left; i <= right; i ++) {
res.add(matrix[top][i]);
}
for (int i = top + 1; i <= bottom - 1; i ++) {
res.add(matrix[i][right]);
}
if (top != bottom) {
for (int i = right; i >= left; i --) {
res.add(matrix[bottom][i]);
}
}
if (left != right) {
for (int i = bottom - 1; i >= top + 1; i --) {
res.add(matrix[i][left]);
}
}
left ++;
right --;
top ++;
bottom --;
}
return res;
}
}
③ 在discuss中看到以下方法:用Iterator来实现,记录2个方向数组,分别表示在x方向,y方向的前进方向。1表示右或是下,-1表示左或是向上,0表示不动作。
// 1: means we are visiting the row by the right direction.
// -1: means we are visiting the row by the left direction.
int[] x = {1, 0, -1, 0};
// 1: means we are visiting the colum by the down direction.
// -1: means we are visiting the colum by the up direction.
int[] y = {0, 1, 0, -1};
这种方向矩阵将会很常用在各种旋转数组上。。。。。。
class Solution{ //2ms
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> res = new ArrayList<Integer>();
int rows = matrix.length;
int cols = matrix[0].length;
if (matrix == null || rows == 0 || cols == 0) {
return res;
}
int visitedRows = 0;//已经遍历过的行
int visitedCols = 0;
int[] x = {1, 0, -1, 0};
int[] y = {0, 1, 0, -1};
// 0: right, 1: down, 2: left, 3: up.
int direct = 0; //方向矩阵的下标
int startx = 0;//记录当前遍历到的横坐标
int starty = 0;
int candidateNum = 0;//记录需要遍历的行数或列数
int step = 0;//记录当前行或列已经遍历过的个数
while (true) {
if (x[direct] == 0) {
//遍历y轴方向.
candidateNum = rows - visitedRows;
} else {
// 遍历x轴方向 candidateNum = cols - visitedCols;
}
if (candidateNum <= 0) {
break;
}
res.add(matrix[startx][starty]);
step ++;
if (step == candidateNum) {
step = 0;
visitedRows += x[direct] == 0 ? 0: 1;
visitedCols += y[direct] == 0 ? 0: 1;
// move forward the direction.
direct ++;
direct = direct % 4;
}
// 根据方向来移动横坐标和纵坐标。
startx += y[direct];
starty += x[direct];
}
return res;
}
}