从生活场景到螺旋矩阵:探索矩阵的螺旋遍历
生活中的螺旋
你有没有注意过,生活中螺旋的形状随处可见?比如蜗牛壳的螺旋纹路、向日葵中心的螺旋排列、甚至是停车场的螺旋坡道。这种由外向内(或由内向外)的螺旋路径,不仅是大自然的奇妙设计,也启发了我们解决一些编程问题。
问题描述
LeetCode第54题"螺旋矩阵"是这样描述的:给你一个 m x n 的矩阵,请按照顺时针螺旋顺序,返回矩阵中的所有元素。
例如:
输入:matrix = [[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的例子来说明:
初始状态:
上边界(top)=0, 下边界(bottom)=2
左边界(left)=0, 右边界(right)=2第一圈:
1. 向右:(0,0)->(0,2) [1,2,3]上边界+1
2. 向下:(0,2)->(2,2) [6,9]右边界-1
3. 向左:(2,2)->(2,0) [8,7]下边界-1
4. 向上:(2,0)->(1,0) [4]左边界+1第二圈:
只剩中间的5,直接添加
Java代码实现
public List<Integer> spiralOrder(int[][] matrix) {List<Integer> result = new ArrayList<>();if (matrix == null || matrix.length == 0) {return result;}// 定义四个边界int top = 0;int bottom = matrix.length - 1;int left = 0;int right = matrix[0].length - 1;while (top <= bottom && left <= right) {// 向右移动,遍历上边界for (int i = left; i <= right; i++) {result.add(matrix[top][i]);}top++; // 收缩上边界// 向下移动,遍历右边界for (int i = top; i <= bottom; i++) {result.add(matrix[i][right]);}right--; // 收缩右边界if (top <= bottom) { // 确保还有行要遍历// 向左移动,遍历下边界for (int i = right; i >= left; i--) {result.add(matrix[bottom][i]);}bottom--; // 收缩下边界}if (left <= right) { // 确保还有列要遍历// 向上移动,遍历左边界for (int i = bottom; i >= top; i--) {result.add(matrix[i][left]);}left++; // 收缩左边界}}return result;
}
实用技巧总结
解决螺旋矩阵问题的关键点:
- 明确移动方向的顺序(右->下->左->上)
- 正确维护和更新边界
- 注意边界条件的判断
- 处理特殊情况(如只有一行或一列)
类似的问题还有:
- 生成螺旋矩阵
- 对角线遍历
- 顺时针打印矩阵
小结
通过螺旋矩阵这道题,我们学会了如何用编程来模拟现实生活中的螺旋路径。这种思维方式不仅能解决算法题,在处理图像处理、游戏开发等实际问题时也很有用。记住,当遇到需要特定顺序遍历矩阵的问题时,可以考虑使用边界收缩的方法,让代码更加清晰和高效!
作者:忍者算法
公众号:忍者算法
我准备了一份刷题清单,以及这些题目的详细题解,覆盖了绝大部分常见面试题。我可以很负责任地说,只要你把这些题真正掌握了,80%的算法面试都能遇到相似题目。公众号回复【刷题清单】获取~