需求I:
Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order.
Example :
Input: [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ] Output: [1,2,3,6,9,8,7,4,5]
分析:
顺时针遍历矩阵,可以看成若干次循环,每次循环分成四部分,第一行,第一列,第二行,第二列。假设每一圈的起始坐标是[startx][starty],其实startx==starty,第一行就是[startx][startx]~[startx][endy],第一列就是[startx+1][endy]~[endx][endy],第二行是[endx][endy-1]~[endx][startx],第二列是[endx-1][startx]~[startx+1][startx]。其中,遍历第一行和第一列的时候不需要判断,只有多于一行时才需要遍历第二行,只有多于一列时才需要遍历第二列,所以遍历后两个边的时候需要判断。
每遍历完一圈,需要更新startx,endx和endy,startx++,endx--,endy--,每次循环的圈会更小。遍历结束的条件是rows<=startx*2或者cols<=startx*2。
代码:
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> res = new LinkedList<Integer>();
//异常处理
if(matrix == null || matrix.length == 0)
return res;
int rows = matrix.length;//行
int cols = matrix[0].length;//列
int startx = 0, endx = rows-1, endy = cols-1;
while(rows > 2*startx && cols > 2*startx){
//打印第一行
for(int i = startx; i <= endy; i++)
res.add(matrix[startx][i]);
//打印第一列
for(int i = startx+1; i <= endx; i++)
res.add(matrix[i][endy]);
//如果有多的行,那么就打印第二行
if(endx > startx){
for(int i = endy-1; i >= startx; i--)
res.add(matrix[endx][i]);
}
//如果有多列,那么就打印最后一列
if(endy > startx)
{
for(int i = endx-1; i > startx; i--)
res.add(matrix[i][startx]);
}
//每次循环之后,需要更新下次循环的起始和结束位置+
startx++;
endx--;
endy--;
}
return res;
}
}
需求II:
Given a positive integer n, generate a square matrix filled with elements from 1 to n2 in spiral order.
Example:
Input: 3 Output: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ]
分析:
和I的区别在于,I是已知矩阵,并且不一定是方阵,求顺时针遍历的结果。II是顺时针填充n*n矩阵。和I思路相似,我们需要创建一个n*n的矩阵,顺时针遍历该数组,依次填充数组。顺时针遍历数组,依旧可以分成若干次循环,每次循环分成四部分,设置一个变量num,从1开始递增,逐步填充矩阵。每遍历完一个圈,需要更新下一个圈的起始和终止坐标,并且要注意整体的循环结束条件。
代码:
class Solution {
public int[][] generateMatrix(int n) {
//思路类似于I,对于n,创建n*n的矩阵,顺时针遍历该矩阵,填充数字即可
//异常处理
if(n < 0)
throw new IllegalArgumentException("illegal parameters");
//创建n*n矩阵,初始化为0
int[][] res = new int[n][n];
//设置每次遍历的起始坐标和结束坐标
int startx = 0, endx = n-1, endy = n-1;
int num = 1;//用数字num填充矩阵
while(n > startx * 2){
//遍历第一行
for(int i = startx; i <= endy; i++)
res[startx][i] = num++;
//遍历第一列
for(int i = startx+1; i <= endx; i++)
res[i][endy] = num++;
//如果有多行,需要遍历第二行
if(endx > startx){
for(int i = endy-1; i >= startx; i--)
res[endx][i] = num++;
}
//如果有多列,需要遍历第二列
if(endy > startx){
for(int i = endx-1; i > startx; i--)
res[i][startx] = num++;
}
startx++;
endx--;
endy--;
}
return res;
}
}