54. 螺旋矩阵

54. 螺旋矩阵

LeetCode题目:54. 螺旋矩阵

我的思路

  • 定义:
    • vector<vector<bool>> vis表示当前位置是否被访问过。
    • (py, px)代表当前元素所在的(行号,列号)。
    • direction代表当前的方向,并规定:
      • 上:0
      • 右:1
      • 下:2
      • 左:3
    • flag表示当前完成访问的个数。

根据上述定义,可以写出AC代码:

class Solution {
public:
    vector<int> ret;
    int m, n;
    vector<vector<bool>> vis;
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        m = matrix.size();
        n = matrix[0].size();
        int size = m * n;
        vis.assign(m, vector<bool>(n, false));
    
        int px = 0;
        int py = 0;
        int flag = 0;
        int direction = 1; // up0;right:1;down2;left3;

        while (true){
            if (0 <= px && px < n && 0 <= py && py < m && !vis[py][px]){
                ret.push_back(matrix[py][px]);
                vis[py][px] = true;
                if (++flag == size){
                    break;
                }
                if (direction == 0){
                    py --;
                }else if (direction == 1){
                    px ++;
                }else if (direction == 2){
                    py ++;
                }else if (direction == 3){
                    px --;
                }
            }else{
                if (direction == 0){
                    direction = 1;
                    py ++;  // 回去
                    px ++;  // 下一个位置
                }else if (direction == 1){
                    direction = 2;
                    px --;
                    py ++;
                }else if (direction == 2){
                    direction = 3;
                    py --;
                    px --;
                }else if (direction == 3){
                    direction = 0;
                    px ++;
                    py --;
                }
            }
        }
        return ret;      
    }
};

执行用时:0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗:6.9 MB, 在所有 C++ 提交中击败了30.35%的用户

  • 复杂度分析:
    • 时间复杂度:O(m*n),需要访问m*n个数字。
    • 空间复杂度:O(m*n),开辟了vis数组。

YouLookDeliciousC的题解

Reference

这里提供一种可以将空间复杂度降低到O(1)的方法,具体思路如下:

  • 1.定义上下左右边界
  • 2.首先从左移动到右,此时第一行已经访问完毕,因此可以将其从图中删除,具体做法是将上边界加1.
  • 3.上边界加1后如果上下边界交错,那么终止循环,返回答案。
  • 4.如果上下边界未交错,那么继续从上到下。接下来操作过程和2.3.4相仿。
  • 5.不断循环,直到某两条边界交错。
class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        vector<int> ret;
        if (matrix.empty()){
            return ret;
        }
        int top = 0;    // 上边界
        int bottom = matrix.size();  // 下边界+1
        int left = 0;   // 左边界
        int right = matrix[0].size(); // 右边界+1
        while (true){
            for (int i = left; i < right; i ++){
                ret.push_back(matrix[top][i]);
            }
            if (++top == bottom)    break;
            for (int i = top; i < bottom; i ++){
                ret.push_back(matrix[i][right-1]);
            }
            if (--right == left)    break;
            for (int i = right - 1; i >= left; i --){
                ret.push_back(matrix[bottom-1][i]);
            }
            if (--bottom == top)    break;
            for (int i = bottom - 1; i >= top; i --){
                ret.push_back(matrix[i][left]);
            }
            if (++left == right)    break;
        }
        return ret;
    }
};
  • 这个思路简直了,天才思路!原来我们把问题都想复杂了,有时候,简单点,别设计那些情节。

执行用时:0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗:6.7 MB, 在所有 C++ 提交中击败了47.86%的用户

  • 复杂度分析:
    • 时间复杂度:O(matrix.size())
    • 空间复杂度: O(1),只使用了可数个变量。
    • 不过从上面的内存消耗中,貌似并不明显,理论和现实还是有差距的。

2021.3.16 0:06

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值