剑指Offer_#29_顺时针打印矩阵
Contents
题目
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
示例 2:
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]
限制:
0 <= matrix.length <= 100
0 <= matrix[i].length <= 100
思路分析
按照书中的思路,打印的过程是逐层打印的,从外到内,每一圈都顺时针的打印。
将整个过程分为两层循环,
- 外层循环:逐渐缩小边界,从最外圈到最内圈。
- 每一圈遍历的起始点是
(start,start)
,每轮循环,start增加1,即边界向内缩小一圈。 - 循环条件:
start * 2 < row && start * 2 <column
,可以这样理解:start
必然在整个矩阵的左半部分和上半部分,超出整个范围,说明每一圈都遍历完成了,循环可以终止。
- 每一圈遍历的起始点是
- 内层循环:顺时针打印某一圈的元素。
- 顺序:模拟顺时针旋转顺序,分别遍历上边界,右边界,下边界,左边界。
- 前提条件:除了上边界之外,其他的边界是否打印是有前提的。
- 从上到下遍历右边界,条件:至少有两行
- 从右到左遍历下边界,条件:至少有两行两列
- 从下到上遍历左边界,条件:至少有三行两列
- 循环边界条件
- 每一圈当中的四个角落位置需要注意,不要重复访问。
- 顺序:模拟顺时针旋转顺序,分别遍历上边界,右边界,下边界,左边界。
解答
class Solution {
int row;
int column;
int[] res;
int x = 0;//res的索引
public int[] spiralOrder(int[][] matrix) {
//ERROR:空数组和null不是一个东西
if(matrix == null || matrix.length == 0) return new int[0];
//打印每一圈的开始位置(0,0),(1,1)...表示为(start,start)
int start = 0;
//ERROR:注意行列的长度不要搞反
row = matrix.length;
column = matrix[0].length;
res = new int[row * column];
//循环条件:开始点(start,start)应该位于矩阵的左半部分和上半部分
//即start应小于行数和列数的一半,可以枚举简单的情况,得到这个规律
//ERROR:不可以写成除法的形式,因为除法会出现向下取整的情况,导致误判
//while(start < (row / 2) && start < (column / 2)){
while(row > 2*start && column > 2*start){
//每次从(start,start)位置开始,顺时针打印一圈
PrintMatrixInCircle(matrix,start);
//start++即打印范围向内缩小一圈
start++;
}
return res;
}
public void PrintMatrixInCircle(int[][] matrix, int start){
//右边界
int endX = column - 1 - start;
//下边界
int endY = row - 1 - start;
//从左到右遍历上边界
for(int i = start;i <= endX;i++){
res[x++] = matrix[start][i];
}
//从上到下遍历右边界
//条件:至少有两行
if(endY > start){
//边界要排除第一个(因为在上边界里访问过了),即i是从start+1开始而非start
for(int i = start + 1;i <= endY;i++){
res[x++] = matrix[i][endX];
}
}
//从右到左遍历下边界
//条件:至少有两行两列
if(start < endX && start < endY){
//同理,要排除第一个
for(int i = endX - 1;i >= start;i--){
res[x++] = matrix[endY][i];
}
}
//从下到上遍历左边界
//条件:至少有三行两列
if(endY - start > 1 && start < endX){
//同理,排除第一个
for(int i = endY - 1;i >= start + 1;--i){
res[x++] = matrix[i][start];
}
}
}
}