54.螺旋矩阵及其题解

今天分享一道算法题:螺旋矩阵

题目如下:

给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。

示例 1:
输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]
示例 2:
输入:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12]
]
输出: [1,2,3,4,8,12,11,10,9,5,6,7]

螺旋矩阵整体思路很简单,从最外层扫描,碰到最边缘的数组(碰壁),转换方向,再碰壁,再转换方向,最后遇到起始元素,也相当于一次碰壁,转换方向,开始第二轮,此时第一层元素就是墙壁,仍然执行碰壁换方向这一原则,最后执行n轮……

按这个方式,扫描,加入列表,我们需要考虑的问题就是:如何控制好“墙壁”以及如何碰到“墙壁”后如何进行换向。(第一轮当然很简单,问题是在第二轮之后怎么搞)

在这里,我们引入一个参数:下标控制数
(对应代码中的add)

首先轮数在这里的定义是只要完成完整的一圈就算一轮,最后一轮不论是半圈还是一圈还是只走了一个元素(3×3),都算做整一轮。
比如:

1 2 3
4 5 6
7 8 9 就是两轮,第一圈走完还走了个第二圈的5,这也算是一轮。

下标控制数则是为了在一轮完成后,对“墙壁”的范围进行缩小,这里用add表示,每完成一轮,add就加1,“墙壁”范围缩小一圈,然后重复第一轮的扫描模式就可以了。

至于扫描与加入列表,则是四个for循环的问题,按顺序是(→)、(↓)、(←)、(↑),注意控制下标即可。

最后就是结束扫描,这个位置很好判断,只能是在每一轮的“上部”和“下部”有可能结束整个数组的扫描,因此在第一和第三个for循环之后判断列表中的元素数是否已经达到了整个矩阵的元素数即可,如果达到了,直接一个break走人。(这也就是为什么代码中的轮数n不用去求它的公式,因为只要发现列表元素数与矩阵元素数吻合就可以结束循环了)

接下来上代码:
//包名已省略

class Solution {
public List spiralOrder(int[][] matrix) {
List list = new ArrayList<>();
int n = Integer.MAX_VALUE;
int add = 0;
if(matrix.length < 1)
return list;
else{
for(int count = 0;count < n;count++){
for(int j = 0 + add;j < matrix[0].length - add;j++){
list.add(matrix[0 + add][j]);
if(j == matrix[0].length - 1 - add)
break;
}
if(list.size() == matrix.length * matrix[0].length)
break;
for(int i = 1 + add;i < matrix.length - add;i++){
list.add(matrix[i][matrix[0].length - 1 - add]);
if(i == matrix.length - 1 - add)
break;
}
for(int j = matrix[0].length - 2 - add;j >= 0 + add;j–){
list.add(matrix[matrix.length - 1 - add][j]);
if(j == 0 + add)
break;
}
if(list.size() == matrix.length * matrix[0].length)
break;
for(int i = matrix.length - 2 - add;i > 0 + add;i–){
list.add(matrix[i][0 + add]);
if(i == 1 + add)
break;
}
add++;
}
return list;
}
}
}

整体代码思路并不复杂,注意控制数组下标,不要越界。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值