在leetCode和牛客上都看到这样一道算法:
描述:
给定一个m x n大小的矩阵(m行,n列),按螺旋的顺序返回矩阵中的所有元素。
示例1
输入:
[[1,2,3],[4,5,6],[7,8,9]]
复制
返回值:
[1,2,3,6,9,8,7,4,5]
算是比较基础的算法,但是一开始做的时候,我脑子出现了卡壳,所以还是记录一下吧。
如下表,这个二维数组,形成了一个3×3的矩阵
1 | 2 | 3 |
---|---|---|
4 | 5 | 6 |
7 | 8 | 9 |
按照瞬时针的方向,也就是:右→下→左→上的顺序循环,达到边界后转换方向,同时对应的边界缩小。
比方说
这个3×3的矩阵一开始的时候,四个方向的变为:
上:0,下:2,左:0,右:2
当走往第一行数,上边的边界缩小,数值+1,变为1,此时达到最右边,从列移动切换为行移动,方向向下。
4 | 5 | 6 |
---|---|---|
7 | 8 | 9 |
向下走完,此时矩阵的最右边都走完了,右边界缩小,数值-1,变为1,方向变为向左
4 | 5 |
---|---|
7 | 8 |
依照这个方式遍历完矩阵。
那么这里有个重要点
通过什么情况判断矩阵遍历完毕呢?
当一个方向走完时,判断当前缩小后的边界是否超过相反边界,如果超过则结束遍历,否则继续往下一个方向移动。
代码:
/**
* 螺旋矩阵
* @param arr 数组
*/
public ArrayList<Integer> spiralMatrix(int [][] arr){
if(arr.length<=0){
return new ArrayList<>();
}
//获取行数
int rows = arr.length;
//获取列数
int ceil = arr[0].length;
//设置边界
int right = ceil-1;
int left = 0;
int down = rows-1;
int up = 0;
ArrayList<Integer> array =new ArrayList<>();
while(true){
//从左往右
for(int i=left;i<=right;i++){
array.add(arr[up][i]);
}
//最上边行走完,上边界+1,若大于下边界,结束遍历
if(++up>down){
break;
}
//从上往下
for(int i = up;i<=down;i++){
array.add(arr[i][right]);
}
//最右边列走完,右边界-1,若小于左边界,结束遍历
if(--right<left){
break;
}
//从右往左走
for(int i = right;i>=left;i--){
array.add(arr[down][i]);
}
//最底部行走完,下边界-1,若小于上边界,结束遍历
if(--down<up){
break;
}
//从下往上走
for(int i = down;i>=up;i--){
array.add(arr[i][left]);
}
//最左边列走完,左边界+1,若大于右边界,结束遍历
if(++left>right){
break;
}
}
return array;
}