54. Spiral Matrix

妖狐艹你老母 2024-04-18 15:24 136阅读 0赞

Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order.

Example 1:

  1. Input:
  2. [
  3. [ 1, 2, 3 ],
  4. [ 4, 5, 6 ],
  5. [ 7, 8, 9 ]
  6. ]
  7. Output: [1,2,3,6,9,8,7,4,5]

Example 2:

  1. Input:
  2. [
  3. [1, 2, 3, 4],
  4. [5, 6, 7, 8],
  5. [9,10,11,12]
  6. ]
  7. Output: [1,2,3,4,8,12,11,10,9,5,6,7]

题意:
给定一个mn 列的矩阵,返回这个矩阵的顺时针螺旋序的各个元素。
即:从先顺时针遍历最外圈,再顺时针遍历此外圈···。

方法:
显然,这就是一个模拟的问题了,跟着问题的要求实现一遍就行。
但是在实现的过程中,需要注意以下 几点:

  1. 顺时针的螺旋,先左->右,再上->下,再右->左,最后下到上。
  2. 每旋转一圈,里面的半径就会变小,同一个位置的元素不能被遍历两次。

基于这两个观察,有两种实现方式:
一、
使用一个标识来标识,某个位置是否被访问过。当遍历的过,发现当前位置越界、或已经被遍历过了,那么就需要改变 遍历的方向。我们使用direct[3]={0,1,-1} 表示 横竖方向的三种增量。

  1. class Solution {
  2. public:
  3. struct _node
  4. {
  5. int x, y;
  6. bool operator <(const _node & rh) const{
  7. return x < rh.x || (x == rh.x && y < rh.y);
  8. }
  9. };
  10. vector<int> spiralOrder(vector<vector<int>>& matrix) {
  11. vector<int> rst;
  12. int m = matrix.size(), n = 0;
  13. if (m > 0)
  14. {
  15. n = matrix[0].size();
  16. }
  17. int x = 0, y = 0;
  18. _node node = { x, y };
  19. set<_node> flags;
  20. int xd = 1, yd = 0;
  21. int direct[3] = { 0, 1, -1 };
  22. while (rst.size() < m*n)
  23. {
  24. if (flags.find({ y,x}) == flags.end() && (x < n) && y < m && y >= 0 && x >= 0)
  25. //说明目前的增长方向是合理的
  26. {
  27. rst.push_back(matrix[y][x]);
  28. flags.insert({ y,x });
  29. }
  30. else
  31. //目前增长方向需要变更
  32. {
  33. x -= xd;//取消之前的一步增长
  34. y -= yd;//取消之前的一步增长
  35. xd = yd = 0;
  36. for (int j = 0; j < 3; j++)
  37. //首先尝试变更 横轴
  38. {
  39. xd = direct[j];
  40. if (flags.find({ y , x + xd }) == flags.end() && y < m && (x + xd) < n && y >= 0 && (x + xd) >= 0)
  41. {
  42. goto label;
  43. }
  44. }
  45. xd = 0;
  46. for (int j = 0; j < 3; j++)
  47. //其次考虑变更纵轴
  48. {
  49. yd = direct[j];
  50. if (flags.find({ y + yd, x }) == flags.end() && (y + yd) < m && (x) < n && (y + yd) >= 0 && (x ) >= 0)
  51. {
  52. goto label;
  53. }
  54. }
  55. yd = 0;
  56. break;//无法再进行下去,说明整个矩阵已经遍历完全。
  57. }
  58. label:
  59. x += xd;
  60. y += yd;
  61. }
  62. return rst;
  63. }
  64. };

二、
使用 4个变量来维护上,下、左、右 已经遍历的顶部行、头部行、左列、右列。

  1. class Solution {
  2. public:
  3. vector<int> spiralOrder(vector<vector<int>>& matrix) {
  4. vector<int> rst;
  5. int m = matrix.size(), n = 0;// MxN
  6. if (m > 0)
  7. {
  8. n = matrix[0].size();
  9. }
  10. int x = 0, y = 0;
  11. int left = 0, right = n - 1, top = 0, bottom = m - 1;
  12. int direction = 0;
  13. while (rst.size()<m*n)
  14. {
  15. if (direction == 0)
  16. {
  17. for (int i = left; i <= right; i++)
  18. {
  19. rst.push_back(matrix[x][i]);
  20. }
  21. top++;//遍历了顶部
  22. y=right;
  23. }
  24. else if (direction == 1)
  25. {
  26. for (int i = top; i <= bottom; i++)
  27. {
  28. rst.push_back(matrix[i][y]);
  29. }
  30. right--;//遍历了右列
  31. x=bottom;
  32. }
  33. else if (direction == 2)
  34. {
  35. for (int i = right; i >= left; i--)
  36. {
  37. rst.push_back(matrix[x][i]);
  38. }
  39. bottom--;//遍历的底部
  40. y=left;
  41. }
  42. else if(direction == 3)
  43. {
  44. for (int i = bottom; i >= top; i--)
  45. {
  46. rst.push_back(matrix[i][y]);
  47. }
  48. left++;//遍历了左列
  49. x=top;
  50. }
  51. direction = (direction + 1 ) % 4;
  52. }
  53. return rst;
  54. }
  55. };

这种方法,空间复杂度低为O(1),但是时间复杂度类似。

发表评论

表情:
评论列表 (有 0 条评论,136人围观)

还没有评论,来说两句吧...

相关阅读