day13-二维数组变换

73矩阵置0

在这里插入图片描述

  • 1.最简单的方法就是另外开一个数组,当前数组遇到0的时候就在新开的数组上对应的行列全部置0,这样空间复杂度要O(MN)
  • 2.开一个m的数组,标记对应的行有没有出现过0,开一个n的数组,标记对应的列有没有出现过0,这样的空间复杂度是O(M+N)
  • 3.在上面的基础上,将第一行和第一列作为m和n的数组,标记对应行和列有没有出现0,有出现过就标记为0,但是这样原本的第一行和列的如果在该位置刚好有0,就需要将第一行和第一列也置为0,于是用两个标记来标注原本的第一行和第一列是否有出现0,这样的空间复杂度是O(1)
  • 4.再在上面的基础上,只使用一个标记变量记录第一列是否原本存在 0。这样,第一列的第一个元素即可以标记第一行是否出现 0。为了防止每一列的第一个元素被提前更新,我们需要从最后一行开始,倒序地处理矩阵元素。
    空间复杂度是O(1)

第三种:

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int m = matrix.size();
        int n = matrix[0].size();
        int flag_row = 0;
        int flag_col = 0;
        for(int i = 0 ; i < m; i++){
           if(matrix[i][0] == 0){
               flag_col = 1;//标记第一列是否原本有0
               break;
           }
        }
        for(int i = 0 ; i < n; i++){
           if(matrix[0][i] == 0){
               flag_row = 1;//标记第一行是否原本有0
               break;
           }
        }
        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] || !matrix[0][j]){
                    matrix[i][j] = 0;
                }
            }
        }
        if(flag_col){
            for(int i = 0 ; i < m; i++) matrix[i][0] = 0;
        }
         if(flag_row){
            for(int i = 0 ; i < n; i++) matrix[0][i] = 0;
        }
   
    }
};

在这里插入图片描述

第四种:

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int m = matrix.size();
        int n = matrix[0].size();
        int flag_col = 0;
        for (int i = 0; i < m; i++) {
            if (!matrix[i][0]) {
                flag_col = 1;
            }
            for (int j = 1; j < n; j++) {
                if (!matrix[i][j]) {
                    matrix[i][0] = matrix[0][j] = 0;
                }
            }
        }
        for (int i = m - 1; i >= 0; i--) {
            for (int j = 1; j < n; j++) {
                if (!matrix[i][0] || !matrix[0][j]) {
                    matrix[i][j] = 0;
                }
            }
            if (flag_col) {
                matrix[i][0] = 0;
            }
        }
    }
};

在这里插入图片描述

289生命游戏

在这里插入图片描述
在这里插入图片描述

这题还是和之前的一样,如果考虑复制一个数组的话,就特别容易实现,但是需要O(MN)的空间复杂度,而本题是要求原地计算的。
还是想到要用标记的方法,怎么标记呢?这个和上一题不一样,上一题对数组进行修改是一整行或者一整列的来,因此用一个标记变量就能记录一整行或者一整列的状态,但是这个是针对每个元素来说都有周围八个(边界的也算八个,我们假设是无边界的,没有在数组之内的都算作是0),因此很难说用常数个标记变量来记录每个元素的状态。

难点在于怎么标记过后还能知道原来是0还是1,而不影响后面对1个数的判断。这种时候就想能不能用当前元素进行标记,因为本来的数组值只有0和1两种,而我们需要改变的也只不过是0变为1,或者1变为0两种状态,我们用2表示0变为1,用-1表示1变为0。

  • 判断周围1的个数的时候除了原来就是1,再多加一种原来是1,现在变为0,也就是-1
  • 遍历一遍标记结束之后,再遍历一遍,将对应的2改为1,-1改为0即可
  • 时间复杂度O(MN),这是无法避免的,空间复杂度O(1)
class Solution {
public:
    void gameOfLife(vector<vector<int>>& board) {
        //-1表示原来是活的后来死了,2表示原来死的后来活了
        int nei[3] = {-1, 0, 1};
        int m = board.size();
        int n = board[0].size();
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                int nei_count = 0;//统计每个位置的周围八个有多少个1
                
                for(int r = 0; r < 3; r++){
                    for(int c = 0; c < 3; c++){
                        if(nei[r] || nei[c]){ //遍历相邻的八个,除去本身的情况
                           int row = i + nei[r];
                           int col = j + nei[c];
                           if(row < m && row >= 0 && col < n && col >= 0 && abs(board[row][col]) == 1){ //活的有1和原来活的-1
                                 nei_count ++;
                           }
                        }
                        
                    }
                }

                if(board[i][j] == 1 && (nei_count < 2 || nei_count > 3)) board[i][j] = -1;
                if(board[i][j] == 0 && nei_count == 3 ) board[i][j] = 2;
            }
        }

        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                if(board[i][j] == 2 ) board[i][j] = 1;
                if(board[i][j] == -1) board[i][j] = 0;
            }
        }

    }
};

在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值