剑指 Offer 29-顺时针打印矩阵c++

----------------------------2020/12/27二刷-----------------------
三个收获
1.自己打出了边界法

//设定边界法
class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        if(matrix.size() == 0) return {};
        int l = 0, r = matrix[0].size()-1;
        int t = 0, d = matrix.size()-1;
        vector<int> ans;
        int index = 0;
        ans.resize((r + 1)*(d + 1));
        while(1) {
            for(int i = l; i <= r; i ++) ans[index ++] = matrix[t][i];
            if(++ t > d) break;
            for(int i = t; i <= d; i ++) ans[index ++] = matrix[i][r];
            if( -- r < l) break;
            for(int i = r; i >= l; i --) ans[index ++] = matrix[d][i];
            if( -- d < t) break;
            for(int i = d; i >= t; i --) ans[index ++] = matrix[i][l];
            if( ++ l > r) break;
            }
            return ans;
    }  
};

2.二刷的过程把之前深度优先的想法实现了,结果
发现纯深度优先是不行的,代码如下

class Solution {
private:
    int rows, cols;
    vector<vector<int>> dir = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};       
    vector<int> ans;
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        if(matrix.size() == 0) return {};
        rows = matrix.size();
        cols = matrix[0].size();
        vector<vector<int>> book (rows, vector<int> (cols, 0));
        int count = rows * cols;
        return dfs(0, 0, count, matrix, ans, book);
    }
    vector<int> dfs(int i, int j, int count,vector<vector<int>> matrix, vector<int> &ans, vector<vector<int>> &book) {
        ans.push_back(matrix[i][j]);
        book[i][j] = 1;
        if(ans.size() == count) return ans;
        for(int k = 0; k <= 3; k ++) {
            int ti = i + dir[k][0];
            int tj = j + dir[k][1];
            if(ti >= rows || ti < 0 || tj >= cols || tj < 0|| book[ti][tj]) continue;
            dfs(ti, tj, count, matrix, ans, book);
        }
        return ans;
    }
};

为什么不行-----自己画一下面这个例子对应矩阵的路径就知道了。
在这里插入图片描述
3.关于引用,如果book和ans不加引用号,形参会开辟一个新的空间,这样对book的修改就没有效果。
所以如果在结构体中定义了book数组和ans数组的话,函数要么加引用,要么不要使用形参直接在函数体里面对其修改
--------------------------------一刷------------------------------------

题目描述

在这里插入图片描述

解法一 深度优先进化版法

一开始的思路是用深度优先做出来,只要指定顺时针方向,用深度优先走一遍,如果没有路可以走直接break即可。
然后就觉得既然拐点处可以特殊处理,按照原本深度优先的思想,每次越界时改变方向即可,省去深度优先尝试其他方向的次数。

class Solution {
private:
    int next[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        if (matrix.size() == 0 || matrix[0].size() == 0) {
            return {};
        }
        int rows = matrix.size();
        int columns = matrix[0].size();
        vector<vector<bool>> book(rows, vector<bool>(columns));
        int count = rows * columns;
        vector<int> order(count);

        int x = 0, y = 0;
        int tx,ty;
        int dir = 0;
        for (int i = 0; i < count; i++) {
            order[i] = matrix[x][y];
            book[x][y] = true;
            tx = x + next[dir][0];
            ty = y + next[dir][1];
            if (tx < 0 || tx >= rows || ty < 0 || ty >= columns || book[tx][ty]) dir = (dir + 1) % 4;
            x += next[dir][0];
            y += next[dir][1];
        }
        return order;
    }
};

在这里插入图片描述
矩阵列数为m,行数为n
时间复杂度O(mn),空间复杂度O(mn);

解法二

一开始思考的过程中,有想过通过前面每次走完一个方向来减少另一个方向的可走次数,然后顺时针四个方向重复,直到一个方向减少到不能走为止。
但是想到深度优先觉得自己已经行了 懒就不没再去实现了。
然后看到住在精选的大佬就是这样做的…
大佬的题解

class Solution {
    public int[] spiralOrder(int[][] matrix) {
        if(matrix.length == 0) return new int[0];
        int l = 0, r = matrix[0].length - 1, t = 0, b = matrix.length - 1, x = 0;
        int[] res = new int[(r + 1) * (b + 1)];
        while(true) {
            for(int i = l; i <= r; i++) res[x++] = matrix[t][i]; // left to right.
            if(++t > b) break;
            for(int i = t; i <= b; i++) res[x++] = matrix[i][r]; // top to bottom.
            if(l > --r) break;
            for(int i = r; i >= l; i--) res[x++] = matrix[b][i]; // right to left.
            if(t > --b) break;
            for(int i = b; i >= t; i--) res[x++] = matrix[i][l]; // bottom to top.
            if(++l > r) break;
        }
        return res;
    }
}

时间复杂度O(m*n),空间复杂度O(1)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值