输入: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]
提示:
m == matrix.length
n == matrix[i].length
1<= m, n <=10-100<= matrix[i][j]<=100----------------------
思考:
根据题目示例 matrix =[[1,2,3],[4,5,6],[7,8,9]] 的对应输出 [1,2,3,6,9,8,7,4,5] 可以发现,顺时针打印矩阵的顺序是 “从左向右、从上向下、从右向左、从下向上” 循环。
因此,考虑设定矩阵的“左、上、右、下”四个边界,模拟以上矩阵遍历顺序。
算法流程:
1、空值处理: 当 matrix 为空时,直接返回空列表 [] 即可。
2、初始化: 矩阵 左、右、上、下 四个边界 l , r , t , b ,用于打印的结果列表 res 。
3、循环打印: “从左向右、从上向下、从右向左、从下向上” 四个方向循环,每个方向打印中做以下三件事 (各方向的具体信息见下表) ;
1、根据边界打印,即将元素按顺序添加至列表 res 尾部;
2、边界向内收缩 1 (代表已被打印);
3、判断是否打印完毕(边界是否相遇),若打印完毕则跳出。
4、返回值: 返回 res 即可。
复杂度分析:
时间复杂度 O(MN): M,N分别为矩阵行数和列数。
空间复杂度 O(1): 四个边界 l , r , t , b 使用常数大小的 额外 空间( res 为必须使用的空间)。
----------------Java 代码利用了 ++ 操作的便利性,详情可见 ++i 和 i++ 的区别 ;
res[x++] 等价于先给 res[x] 赋值,再给 x 自增 1 ;
++t > b 等价于先给 t 自增 1 ,再判断 t > b 逻辑表达式。
----------------------classSolution{publicint[]spiralOrder(int[][] matrix){if(matrix ==null|| matrix.length ==0)returnnewint[0];int left =0;//左边界int right = matrix[0].length -1;//右边界:也即矩阵的列数,每行多少个元素int down = matrix.length -1;//下边界:也即矩阵的行数int up =0;//上边界: 代表当前行int index =0;//结果集指针int[] res =newint[(down +1)*(right +1)];while(true){for(int i = left; i <= right; i++) res[index++]= matrix[up][i];//从左向右if(++up > down)break;//当前行超过矩阵最下面一行则结束循环for(int i = up; i <= down; i++) res[index++]= matrix[i][right];//从上向下if(left >--right)break;//left 超过右边界 则结束循环for(int i = right; i >= left; i--) res[index++]= matrix[down][i];//从右向左if(up >--down)break;//当前行超过矩阵最下面一行则结束循环for(int i = down; i >= up; i--) res[index++]= matrix[i][left];//从下往上if(++left > right)break;}return res;}}/**
从左向右 left--right up++ 特判: up > down break
从上向下 up-- down right-- 特判: left > right break
从右向左 right--left down-- 特判: up > down break;
从下往上 down-- up left++ 特判: left > right
*/