概要:
本文以初学者视角,详细讲解了LeetCode螺旋矩阵相关题目(54、59、LCR146)的解题思路与代码实现,带你掌握二维数组的螺旋遍历与生成技巧。内容通俗易懂,配有丰富注释和案例,助你轻松突破算法难关!
一、开场:你真的会“螺旋”吗?
你是否在刷LeetCode时遇到过这样的题目:让你顺时针“螺旋”地遍历一个二维数组,或者直接生成一个螺旋排列的矩阵?刚看到题目时,很多新手都会一脸懵逼:“这怎么下手?”其实,螺旋矩阵是二维数组操作的经典题型,掌握它不仅能提升你的代码能力,还能让你在面试中脱颖而出!
二、题目介绍
1. LeetCode 54:螺旋矩阵
给定一个 m 行 n 列的矩阵,按顺时针螺旋顺序返回矩阵中的所有元素。
示例:
输入:[[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
2. LeetCode 59:螺旋矩阵 II
给定正整数 n,生成一个 n x n 的矩阵,元素从 1 到 n²,按顺时针螺旋顺序排列。
示例:
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
3. LCR 146:螺旋遍历二维数组
给定一个二维数组,返回其螺旋遍历的结果。
三、暴力法?不如用“边界收缩”!
很多同学一开始会想到用“标记法”或者“visited数组”来记录哪些元素被访问过,但这样写起来又麻烦又容易出错。其实,最优雅的做法是用边界收缩法,也就是用四个变量(上、下、左、右)来控制遍历的范围,每遍历一圈就收缩一次边界。
四、LeetCode 54 螺旋遍历代码详解
var spiralOrder = function(matrix) {
if (!matrix.length || !matrix[0].length) return [];
let res = [];
let left = 0, right = matrix[0].length - 1;
let top = 0, bottom = matrix.length - 1;
while (left <= right && top <= bottom) {
// 从左到右
for (let j = left; j <= right; j++) res.push(matrix[top][j]);
top++;
// 从上到下
for (let i = top; i <= bottom; i++) res.push(matrix[i][right]);
right--;
if (top <= bottom) {
// 从右到左
for (let j = right; j >= left; j--) res.push(matrix[bottom][j]);
bottom--;
}
if (left <= right) {
// 从下到上
for (let i = bottom; i >= top; i--) res.push(matrix[i][left]);
left++;
}
}
return res;
};
技术点解析
- 四个边界变量:
left、right、top、bottom,每次遍历一圈后收缩边界。 - 顺序:右→下→左→上,循环往复。
- 边界判断:每次遍历后都要判断是否还有剩余行/列,防止重复遍历。
五、LeetCode 59 螺旋生成代码详解
var generateMatrix = function(n) {
let matrix = Array.from({length: n}, () => Array(n).fill(0));
let num = 1, left = 0, right = n - 1, top = 0, bottom = n - 1;
while (left <= right && top <= bottom) {
for (let j = left; j <= right; j++) matrix[top][j] = num++;
top++;
for (let i = top; i <= bottom; i++) matrix[i][right] = num++;
right--;
if (top <= bottom) {
for (let j = right; j >= left; j--) matrix[bottom][j] = num++;
bottom--;
}
if (left <= right) {
for (let i = bottom; i >= top; i--) matrix[i][left] = num++;
left++;
}
}
return matrix;
};
技术点解析
- 初始化矩阵:用
Array.from快速生成二维数组。 - 填充顺序:和遍历类似,只不过是赋值而不是读取。
- 计数器:用
num记录当前要填入的数字。
六、LCR 146 螺旋遍历代码简析
LCR 146其实和54题本质一样,都是螺旋遍历二维数组。你可以直接复用54题的代码思路。
七、常见问题与易错点
- 边界条件:一定要注意每次收缩边界后,判断是否还有剩余行/列,防止死循环或重复遍历。
- 单行/单列矩阵:要特别小心,防止越界。
- 空矩阵:提前返回空数组。
八、进阶思考
- 如果让你逆时针螺旋遍历,应该怎么改?
- 如果矩阵不是方阵,而是m×n的长方形,代码还能用吗?
- 如何用递归实现螺旋遍历?
这些问题都可以通过灵活调整边界变量和遍历顺序来解决,建议大家多动手实践!
九、总结
螺旋矩阵题型看似复杂,其实只要掌握了“边界收缩法”,无论是遍历还是生成,都能轻松搞定。建议大家多画图、多模拟,理解每一步的边界变化,代码自然就会写得又快又准!