📝 标题:搞懂二维数组螺旋遍历:从原理到代码实现
在算法面试和日常开发中,二维数组的螺旋遍历是一个高频考点。它不仅考验我们对数组操作的熟悉程度,还能锻炼逻辑思维能力。今天我们就从原理出发,一步步拆解这个经典问题,并用Java、Python、C++三种主流语言实现代码。
🧩 什么是二维数组螺旋遍历?
螺旋遍历,顾名思义,就是按照顺时针(或逆时针)的螺旋顺序,依次访问二维数组中的每个元素。比如对于如下二维数组:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
它的螺旋遍历结果是:1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10
🚀 核心解题思路
要实现螺旋遍历,关键是要明确每一圈遍历的边界,通过不断缩小边界来完成整个数组的遍历。我们可以用四个变量来定义当前遍历的范围:
top:当前遍历的顶部行号bottom:当前遍历的底部行号left:当前遍历的左边界列号right:当前遍历的右边界列号
具体步骤如下:
- 从左到右遍历顶部行,遍历完成后
top++ - 从上到下遍历右边界列,遍历完成后
right-- - 如果
top <= bottom,从右到左遍历底部行,遍历完成后bottom-- - 如果
left <= right,从下到上遍历左边界列,遍历完成后left++ - 重复上述步骤,直到
top > bottom或left > right
💻 代码实现
🐍 Python 实现
def spiral_order(matrix):
if not matrix or not matrix[0]:
return []
res = []
top, bottom = 0, len(matrix) - 1
left, right = 0, len(matrix[0]) - 1
while top <= bottom and left <= right:
# 从左到右遍历顶部行
for i in range(left, right + 1):
res.append(matrix[top][i])
top += 1
# 从上到下遍历右边界列
for i in range(top, bottom + 1):
res.append(matrix[i][right])
right -= 1
# 从右到左遍历底部行(需要判断是否还有行)
if top <= bottom:
for i in range(right, left - 1, -1):
res.append(matrix[bottom][i])
bottom -= 1
# 从下到上遍历左边界列(需要判断是否还有列)
if left <= right:
for i in range(bottom, top - 1, -1):
res.append(matrix[i][left])
left += 1
return res
# 测试
matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]
print(spiral_order(matrix))
☕ Java 实现
import java.util.ArrayList;
import java.util.List;
public class SpiralMatrix {
public static List<Integer> spiralOrder(int[][] matrix) {
List<Integer> res = new ArrayList<>();
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return res;
}
int top = 0, bottom = matrix.length - 1;
int left = 0, right = matrix[0].length - 1;
while (top <= bottom && left <= right) {
// 从左到右遍历顶部行
for (int i = left; i <= right; i++) {
res.add(matrix[top][i]);
}
top++;
// 从上到下遍历右边界列
for (int i = top; i <= bottom; i++) {
res.add(matrix[i][right]);
}
right--;
// 从右到左遍历底部行
if (top <= bottom) {
for (int i = right; i >= left; i--) {
res.add(matrix[bottom][i]);
}
bottom--;
}
// 从下到上遍历左边界列
if (left <= right) {
for (int i = bottom; i >= top; i--) {
res.add(matrix[i][left]);
}
left++;
}
}
return res;
}
public static void main(String[] args) {
int[][] matrix = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
System.out.println(spiralOrder(matrix));
}
}
➕ C++ 实现
# <iostream>
# <vector>
using namespace std;
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> res;
if (matrix.empty() || matrix[0].empty()) {
return res;
}
int top = 0, bottom = matrix.size() - 1;
int left = 0, right = matrix[0].size() - 1;
while (top <= bottom && left <= right) {
// 从左到右遍历顶部行
for (int i = left; i <= right; ++i) {
res.push_back(matrix[top][i]);
}
top++;
// 从上到下遍历右边界列
for (int i = top; i <= bottom; ++i) {
res.push_back(matrix[i][right]);
}
right--;
// 从右到左遍历底部行
if (top <= bottom) {
for (int i = right; i >= left; --i) {
res.push_back(matrix[bottom][i]);
}
bottom--;
}
// 从下到上遍历左边界列
if (left <= right) {
for (int i = bottom; i >= top; --i) {
res.push_back(matrix[i][left]);
}
left++;
}
}
return res;
}
int main() {
vector<vector<int>> matrix = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
vector<int> result = spiralOrder(matrix);
for (int num : result) {
cout << num << " ";
}
cout << endl;
return 0;
}
🎯 边界情况处理
在实现过程中,我们需要特别注意以下边界情况:
- 空数组或空行:直接返回空列表
- 只有一行的数组:直接从左到右遍历
- 只有一列的数组:直接从上到下遍历
- 遍历过程中出现
top > bottom或left > right的情况,要及时终止循环
📌 总结
二维数组的螺旋遍历问题,核心在于通过边界变量来控制遍历范围,逐步缩小遍历区域。只要理清了遍历的顺序和边界条件,用任何语言都能轻松实现。希望这篇文章能帮助你彻底搞懂这个经典算法问题!