7.12 数组中等&简单 498 566 48 73

498 对角线遍历

给你一个大小为 m x n 的矩阵 mat ,请以对角线遍历的顺序,用一个数组返回这个矩阵中的所有元素。
很明显这道题最起码的时间复杂度是O(m*n),直接模拟就好。

class Solution {
public:
    vector<int> findDiagonalOrder(vector<vector<int>>& mat) {
        //类似于螺旋数组,找出边界,变方向
        int m = mat.size() , n = mat[0].size() , tar = m*n , num = 0;
        vector<int> res(tar);
        int i = 0 , j = 0;
        bool rightUp = 1 ;
        while(num < tar){
            res[num++] = mat[i][j];
            //遍历
            if(rightUp){
                i--;j++;
            }else{
                i++;j--;
            }
            //出界判断
            if(i < 0){ i = 0 ; rightUp = 0;}//上出界,右移,行数不变
            else if(j < 0){ j = 0 ; rightUp = 1;}//左出界,下移,列数不变
            else if(i == m){
                if(j < 0){
                    j++;
                }
                i = m - 1 ; j++ ;rightUp =1;
            }//下出界,右移,行数不变
            else if(j == n){ 
                if(i < 0){
                    i++;
                }
                j = m - 1 ; i++ ;rightUp =0;
            }
        }
        return res;

    }
};

优化:

class Solution {
public:
    vector<int> findDiagonalOrder(vector<vector<int>>& mat) {
        int m = mat.size(), n = mat[0].size();
        vector<int> res;
        int i = 0, j = 0;
        bool rightUp = true;
        
        while (res.size() < m * n) {
            res.push_back(mat[i][j]);
            if (rightUp) {
                if (j == n - 1) {
                    i++;
                    rightUp = false;
                } else if (i == 0) {
                    j++;
                    rightUp = false;
                } else {
                    i--;
                    j++;
                }
            } else {
                if (i == m - 1) {
                    j++;
                    rightUp = true;
                } else if (j == 0) {
                    i++;
                    rightUp = true;
                } else {
                    i++;
                    j--;
                }
            }
        }
        return res;
    }
};

566 重塑矩阵

在 MATLAB 中,有一个非常有用的函数 reshape ,它可以将一个 m x n 矩阵重塑为另一个大小不同(r x c)的新矩阵,但保留其原始数据。
给你一个由二维数组 mat 表示的 m x n 矩阵,以及两个正整数 r 和 c ,分别表示想要的重构的矩阵的行数和列数。
重构后的矩阵需要将原始矩阵的所有元素以相同的 行遍历顺序 填充。
如果具有给定参数的 reshape 操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。

reshape()函数比较重要的一点是,首先应该判断是否可以进行重构:

思路:首先检查原始矩阵的元素总数是否等于新矩阵的元素总数。如果原始矩阵的元素数量与目标矩阵的元素数量不匹配,则不能进行重构。
剩余就比较简单,直接遍历整个mat , 所以时间复杂度最低也应该是O(m*n),通过计数判定对应的reshape后的元素的位置就好。

class Solution {
public:
    vector<vector<int>> matrixReshape(vector<vector<int>>& mat, int r, int c) {
        vector<vector<int>> res(r , vector<int>(c));
        int count = 0 , m = mat.size() , n = mat[0].size();
        if(r*c != m*n){return mat;}
        //行数 为 count / r , 列数 为 count % c
        for(int i = 0 ; i < m ; i++){
            for(int j = 0 ; j < n ;j++){
                int x = count / c , y = count % c; 
                res[x][y] = mat[i][j];
                count++;
            }
        }
        return res;

    }
};

官方题解中将i和j都替换为count/n和count %n了。

 for (int x = 0; x < m * n; ++x) {
            ans[x / c][x % c] = nums[x / n][x % n];
        }

48 旋转图像

给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

在这里插入图片描述
类似于昨天看到的螺旋矩阵,不断变化边界,并且保证每一轮的规律一致。

class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        //空间复杂度为O(1)
        //虽然知道旋转的规律,i , j---> j ,n - 1 -j行列互换
        //但是很明显原地旋转需要一圈一圈的推进,类似于华容道
        //拿出一圈的一个,每层从i行移动到n-i-1,一共是要进行n/2次
        int n = matrix.size(); 
        for(int i = 0 ; i < n / 2 ; i++){
            for(int j = i ; j < n - i - 1 ; j++){
                int temp = matrix[i][j];
                matrix[i][j] = matrix[n - j - 1][i];
                matrix[n - 1 - j][i] = matrix[n - i - 1][n - j - 1];
                matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1];
                matrix[j][n - i - 1] = temp;
            }
        }
    }
};

73 矩阵置零

给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。

思路:确定零的位置,标记,置零,根据标记的方法分为两类,只写了第2个方法。

第一类:辅助空间通过设置两个分别以 m 和 n为长度的一维行列数组,遍历matrix,如果元素为0,在对应的行列数组中置1,标示这一行/列就需要置零;
第二类:空间复杂度为O(1)使用矩阵的第一行和第一列作为标记来记录哪些行和列需要置零。
a. 首先,遍历第一行和第一列,判定是否有0;
b. 接着就从i = 1 , j= 1开始遍历,如果为0,就令这一行的开头[i][0]或这一列的开头[0][j]为0;
c.置零分为两步: 第一步就是从i = 1 j = 1开始置零只要[i][0] == 0 || [0][j] == 0就置零,,第二步,是通过第一轮判定的第一行第一列是否为0,对其置零。

就是取巧,讲真

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int m = matrix.size(), n = matrix[0].size();
        bool firstRowZero = false, firstColZero = false;

       //第一列/行判定是否为0
        for (int i = 0; i < m; ++i) {
            if (matrix[i][0] == 0) {
                firstColZero = true;
                break;
            }
        }
        for (int j = 0; j < n; ++j) {
            if (matrix[0][j] == 0) {
                firstRowZero = true;
                break;
            }
        }

        //标记0的位置
        for (int i = 1; i < m; ++i) {
            for (int j = 1; j < n; ++j) {
                if (matrix[i][j] == 0) {
                    matrix[i][0] = 0;
                    matrix[0][j] = 0;
                }
            }
        }

        //置零
        for (int i = 1; i < m; ++i) {
            for (int j = 1; j < n; ++j) {
                if (matrix[i][0] == 0 || matrix[0][j] == 0) {
                    matrix[i][j] = 0;
                }
            }
        }

        //第一列/行置零
        if (firstRowZero) {
            for (int j = 0; j < n; ++j) {
                matrix[0][j] = 0;
            }
        }
        if (firstColZero) {
            for (int i = 0; i < m; ++i) {
                matrix[i][0] = 0;
            }
        }
    }
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值