内容目录
54. 螺旋矩阵
一,描述
难度:中等
给你一个 m
行 n
列的矩阵 matrix
,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
示例 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]
提示:
m == matrix.length
n == matrix[i].length
1 <= m, n <= 10
-100 <= matrix[i][j] <= 100
二,思路:
方法一:
逐层剥开法:
- 分为四步:从左到右,从上到下,从右到左,从下到上。
- 都保持左闭右开,并且外层控制循环(取min(m,n)/2)。
- 处理特殊情况,如m==n且都是奇数时,还有最中心一个值未添加。
- m与n不等且还有值没有添加进res数组,此处有m,n中最小值为奇数的时候,才有未添加分情况刚讨论进行添加。
- 最小值是偶数时,表明已经添加完毕了,如m=2,n=3时,一圈就添加完毕。
方法二:
碰壁走路法:
- 设置一个dirs[4] [2]来记录数组的行进方向(右下左上)。
- 总共记录m*n次,标记记录过得值。
- 记录一次,判断下一次是否碰壁或走过,如果是则换方向。按照右下左上的顺序一直进行。
- 更新下一次记录的坐标i,j。下次进行记录。
三,代码
方法一:
func spiralOrder(matrix [][]int) []int {
m := len(matrix);
n := len(matrix[0]);
w := min(m,n)/2;
res := make([]int,0);
for i:=0;i<w;i++{
for lr:=i;lr<(n-i-1);lr++{
res = append(res,matrix[i][lr]);
}
for tb:=i;tb<(m-i-1);tb++{
res = append(res,matrix[tb][n-i-1]);
}
for rl:=n-i-1;rl>i;rl--{
res = append(res,matrix[m-i-1][rl]);
}
for bt:=m-i-1;bt>i;bt--{
res = append(res,matrix[bt][i]);
}
}
if(m==n && (m%2)==1){
res = append(res,matrix[w][w]);
}else if(m < n && (m%2)==1){
for i:=w;i<=(w+n-m);i++{
res = append(res,matrix[w][i]);
}
}else if(m > n && (n%2)==1){
for i:=w;i<=(w+m-n);i++{
res = append(res,matrix[i][w]);
}
}
return res;
}
方法二:
var dirs = [4][2]int{{0,1},{1,0},{0,-1},{-1,0}} //右下左上
func spiralOrder(matrix [][]int) []int {
m := len(matrix);
n := len(matrix[0]);
res := make([]int,m*n);
i,j,dir :=0,0,0;
for k := range res{
res[k] = matrix[i][j];
matrix[i][j] = math.MaxInt;
x,y := i+dirs[dir][0], j+dirs[dir][1];
if(x<0 || x>=m || y<0 || y>=n || matrix[x][y]==math.MaxInt){
dir = (dir+1)%4;
}
i = i+dirs[dir][0];
j = j+dirs[dir][1];
}
return res;
}