一、题目内容 中等

给一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的n x n正方形矩阵matrix

示例1:

5. 螺旋矩阵II(59) - 图1 输入:n = 3 输出:[[1,2,3],[8,9,4],[7,6,5]]

示例2:

输入:n = 1 输出:[[1]]

提示:

  • 1 <= n <= 20

    二、解题思路

    如果要写出正确的二分法一定要坚持循环不变量原则
    而求解本题依然是要坚持循环不变量原则。
    模拟顺时针画矩阵的过程:

  • 填充上行从左到右

  • 填充右列从上到下
  • 填充下行从右到左
  • 填充左列从下到上

由外向内一圈一圈这么画下去。
可以发现这里的边界条件非常多,在一个循环中,如此多的边界条件,如果不按照固定规则来遍历,那就是一进循环深似海,从此 offer 是路人
这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。
那么我按照左闭右开的原则,来画一圈,大家看一下:
5. 螺旋矩阵II(59) - 图2
这里每一种颜色,代表一条边,我们遍历的长度,可以看出每一个拐角处的处理规则,拐角处让给新的一条边来继续画。
这也是坚持了每条边左闭右开的原则。

  1. n2 的矩形,有 n / 2 个循环

    三、具体代码

    1. /**
    2. * @param {number} n
    3. * @return {number[][]}
    4. */
    5. var generateMatrix = function (n) {
    6. const result = new Array(n).fill(1).map(_ => new Array(n).fill(1))
    7. let startx = 0, starty = 0
    8. let loop = Math.floor(n / 2) // 循环几圈
    9. let count = 1 // 填充的数字
    10. let offset = 1 // 控制遍历时,边界的范围
    11. const mid = n % 2 ? Math.floor(n / 2) : 0 // 圈的中心,如果是奇数就需要填充
    12. while (loop--) {
    13. // 从左到右填充,左开右闭
    14. for (; startx < n - offset; startx++) {
    15. result[starty][startx] = count++
    16. }
    17. // 从上到下填充,左开右闭
    18. for (; starty < n - offset; starty++) {
    19. result[starty][startx] = count++
    20. }
    21. // 从右到左填充,左开右闭
    22. for (; startx > offset - 1; startx--) {
    23. result[starty][startx] = count++
    24. }
    25. // 从下到上填充,左开右闭
    26. for (; starty > offset - 1; starty--) {
    27. result[starty][startx] = count++
    28. }
    29. startx++
    30. starty++
    31. offset++
    32. }
    33. if (mid !== 0) result[mid][mid] = count
    34. return result
    35. };

    四、其他解法