一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
1.题目一
59. 螺旋矩阵 II
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
示例 1:
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
示例 2:
输入:n = 1
输出:[[1]]
思路
如果要写出正确的二分法一定要坚持循环不变量原则。
而求解本题依然是要坚持循环不变量原则。
模拟顺时针画矩阵的过程:
- 填充上行从左到右
- 填充右列从上到下
- 填充下行从右到左
- 填充左列从下到上
由外向内一圈一圈这么画下去。
可以发现这里的边界条件非常多,在一个循环中,如此多的边界条件,如果不按照固定规则来遍历,那就是非常复杂
这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开又闭的原则,这样这一圈才能按照统一的规则画下来。
生成一个 n×n 空矩阵 mat,随后模拟整个向内环绕的填入过程: 定义当前左右上下边界 l,r,t,b,初始值 num = 1,迭代终止值 tar = n * n; 当 num <= tar 时,始终按照 从左到右 从上到下 从右到左 从下到上 填入顺序循环,每次填入后: 执行 num += 1:得到下一个需要填入的数字; 更新边界:例如从左到右填完后,上边界 t += 1,相当于上边界向内缩 1。 使用num <= tar而不是l < r || t < b作为迭代条件,是为了解决当n为奇数时,矩阵中心数字无法在迭代过程中被填充的问题。
代码
var generateMatrix = function (n) {
let left = 0, top = 0;
let right = n-1, bot = n-1;
let res = [];
for (let k = 0; k < n; k++) {
res.push([]);
}
let num = 1
while (num <= n*n) {
for (let i = left; i <= right; i++) {
res[top][i] = num;
num++
}
top++
for (let i = top; i <=bot; i++) {
res[i][right] = num;
num++
}
right--
for (let i = right; i >= left; i--) {
res[bot][i] = num
num++
}
bot--
for (let i = bot; i >= top; i--) {
res[i][left] = num
num++
}
left++
}
return res
};