54. 螺旋矩阵

给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。 :::info 示例 1:
输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]
示例 2:
输入:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12]
]
输出: [1,2,3,4,8,12,11,10,9,5,6,7] :::

思路

方法一

记录一个数组,按照右、下、左、上的方向不断从(0,0)前进。
当遇到边界或者已经访问过的元素时,切换方向,每访问一个元素就把结果放入res中,直到res数组长度与矩阵大小一致时,就返回结果。
这里方向用 dirs 表示 4 个方向对应的偏移坐标,通过 currentIndex 指针不断递增来维护当前的方向,由于可能会超出方向数组的长度,所以每次取值都对 4 取余即可。

  1. var spiralOrder = function(matrix) {
  2. const m = matrix.length;
  3. if (!m) return [];
  4. const n = matrix[0].length;
  5. // 遍历方向
  6. const dirs = [
  7. [0, 1], // 右
  8. [1, 0], // 下
  9. [0, -1], // 左
  10. [-1, 0] // 上
  11. ]
  12. // 记录被访问过的元素
  13. let visited = [];
  14. for (let i = 0; i < m; i++) {
  15. visited[i] = [];
  16. }
  17. // 结果数组
  18. const res = [];
  19. // 矩阵长度
  20. const matrixLen = m * n;
  21. let curIndex = 0;
  22. // 确定当前遍历元素是否到达边界或者已经遍历过
  23. const isValid = (x, y) => {
  24. return x >= 0 && x < m && y >= 0 && y < n && !visited[x][y];
  25. }
  26. const helper = (x, y) => {
  27. res.push(matrix[x][y]);
  28. if (res.length === matrixLen) return res;
  29. visited[x][y] = true;
  30. let [diffX, diffY] = dirs[curIndex % 4];
  31. let [nextX, nextY] = [x + diffX, y + diffY];
  32. if (!isValid(nextX, nextY)) {
  33. [diffX, diffY] = dirs[++curIndex % 4];
  34. nextX = x + diffX;
  35. nextY = y + diffY;
  36. }
  37. helper(nextX, nextY);
  38. }
  39. helper(0, 0);
  40. return res;
  41. };

方法二

直接遍历,每遍历完一层后,将对应方向的位置缩小或增大即可。

  1. var spiralOrder = function(matrix) {
  2. if(!matrix.length) return []
  3. let n = matrix.length
  4. let m = matrix[0].length
  5. let total = n*m
  6. let top = 0,bottom = n-1
  7. let left = 0,right = m-1
  8. let res = []
  9. while(res.length < total){
  10. for(let i=left;i<=right;i++) res.push(matrix[top][i]) // 从左到右
  11. top++
  12. for(let i=top;i<=bottom;i++) res.push(matrix[i][right]) // 从上到下
  13. right--
  14. /* 因为n 和 m 不相同的时候,最后可能会留一列或一行,避免重复计算,总数够了直接跳出去 */
  15. if(res.length === total) break
  16. for(let i=right;i>=left;i--) res.push(matrix[bottom][i]) // 从右到左
  17. bottom--
  18. for(let i=bottom;i>=top;i--) res.push(matrix[i][left]) // 从下到上
  19. left++
  20. }
  21. return res
  22. };

59. 螺旋矩阵 II

给定一个正整数 n,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。 :::info 示例:
输入: 3
输出:
[
[ 1, 2, 3 ],
[ 8, 9, 4 ],
[ 7, 6, 5 ]
] :::

思路

先生成nn矩阵并将元素置为0,剩下按照 *螺旋矩阵I 的解题思路去做即可。

  1. var generateMatrix = function(n) {
  2. if (!n) return [];
  3. // 创建矩阵
  4. const res = new Array(n).fill(0).map(() => new Array(n).fill(0));
  5. // 当前元素值
  6. let curValue = 1;
  7. // 当前边界
  8. let top = 0, bottom = n - 1;
  9. let left = 0, right = n - 1;
  10. // 矩阵长度
  11. let total = n * n;
  12. while (curValue <= total) {
  13. for (let i = left; i <= right; i++) {
  14. res[top][i] = curValue;
  15. curValue++;
  16. }
  17. top++;
  18. for (let i = top; i <= bottom; i++) {
  19. res[i][right] = curValue;
  20. curValue++;
  21. }
  22. right--;
  23. for (let i = right; i >= left; i--) {
  24. res[bottom][i] = curValue;
  25. curValue++;
  26. }
  27. bottom--;
  28. for (let i = bottom; i >= top; i--) {
  29. res[i][left] = curValue;
  30. curValue++
  31. }
  32. left++;
  33. }
  34. return res
  35. };