C++矩阵置零---原地算法(附三种解法)

在这里插入图片描述
如题只要发现一个元素为0,那么它所在的行和列都要置零。
方法一:使用两个数组只要发现某个元素为0,就将这一行或这一列的头元素置true,然后再遍历矩阵,只要某个元素对应的行或列头元素为true,那么对应元素就应该置换为0。//时间复杂度为o(mn),空间复杂度o(m+n);优点代码简短,缺点空间复杂度略高。
方法二:我们首先预处理出两个标记变量,用它们来标记第一行和第一列是否有0元素,接着遍历(1:m-1:1:n-1)元素如果出现零元素,那么将矩阵对应这一列和行头元素同时置0;再接着遍历1:m-1:1:n-1)一次,发现某个元素所对应的行或列头元素为0时,该元素就应该置0;最后在判断是否将第一行或者第一列元素置0/时间复杂度为o(mn),空间复杂度o(1);优点代码空间复杂度低,缺点代码冗杂。
方法三:只用一个变量,用它来标记第一列是否有0元素,接着遍历(0:m-1:1:n-1),同样的如果出现零元素,那么将矩阵对应这一列和行头元素同时置0;再接着遍历1:m-1:1:n-1)一次,不同的是这种方法第二次遍历置换元素需要从最后一行开始倒着置换,因为为了防止第一行元素被提前置换使得后续元素受到影响,最后再判断第一列元素是否全置0./时间复杂度为o(mn),空间复杂度o(1);为方法二的进一步优化

#include <iostream>
#include<vector>
using namespace std;
class Solution {//方法一
public:
    void setZeroes(vector<vector<int>>& matrix) {
        vector<bool> t1(matrix.size());//只要发现那个元素为0,就将这一行或这一列的头元素置true
        vector<bool> t2(matrix[0].size());

        for (int i = 0; i < matrix.size(); i++) {
            for (int j = 0; j < matrix[i].size(); j++) {
                if (matrix[i][j] == 0) {
                    t1[i] = t2[j] = true;
                }
            }
        }
        for (int i = 0; i < matrix.size(); i++) {
            for (int j = 0; j < matrix[i].size(); j++) {
                if (t1[i] || t2[j]) {//判断这一行或者这一列头元素如果为true,那么这个元素一定为0
                    matrix[i][j] = 0;
                }
            }
        }
    }
};//时间复杂度为o(mn),空间复杂度o(m+n);
class Solution1 {//方法二
public:
    void setZeroes(vector<vector<int>>& matrix) {
       bool dyh = false;
       bool dyl = false;
       for (int i = 0; i < matrix.size(); i++) {
           if (matrix[i][0] == 0) {
               dyl = true;
           }
        }
       for (int i = 0; i < matrix[0].size(); i++) {
           if (matrix[0][i] == 0) {
               dyh = true;
           }
       }
       for (int i = 1; i < matrix.size(); i++) {
           for (int j = 1; j < matrix[0].size(); j++) {
               if (matrix[i][j] == 0) {
                   matrix[i][0] = matrix[0][j] = 0; //只要发现那个元素为0,就将这一行或这一列的头元素置true
               }
           }
      }
       for (int i = 1; i < matrix.size(); i++) {
           for (int j = 1; j < matrix[0].size(); j++) {
               if (matrix[i][0] == 0 || matrix[0][j] == 0) {
                   matrix[i][j] = 0;
           }
           }
       }
       if (dyl) {
           for (int i = 0; i < matrix.size(); i++) {
               matrix[i][0] = 0;
           }
       }
       if (dyh) {
           for (int i = 0; i < matrix[0].size(); i++) {
               matrix[0][i] = 0;
           }
       }
    }
};//时间复杂度:O(mn),其中 mm 是矩阵的行数,nn 是矩阵的列数。我们至多只需要遍历该矩阵两次。
//空间复杂度:O(1),我们只需要常数空间存储若干变量。
class Solution2 {//方法三
public:
    void setZeroes(vector<vector<int>>& matrix) {
        bool dyl = false;
        for (int i = 0; i < matrix.size(); i++) {
            if (matrix[i][0] == 0) {
                dyl = true;
            }
        }
        for (int i = 0; i < matrix.size(); i++) {
            for (int j = 1; j < matrix[0].size(); j++) {
                if (matrix[i][j] == 0) {
                    matrix[i][0] = matrix[0][j] = 0; //只要发现那个元素为0,就将这一行或这一列的头元素置true
                }
            }
        }
        for (int i = matrix.size() - 1; i >= 0; i--) {
            for (int j = 1; j < matrix[0].size(); j++) {
                if (matrix[i][0] == 0 || matrix[0][j] == 0) {//防止第一行元素被提前置0,所以从最后一行开始替换
                    matrix[i][j] = 0;
                }
            }
        }
            if (dyl) {
                for (int i = 0; i < matrix.size(); i++) {
                    matrix[i][0] = 0;
                }
            }
    }
};//时间复杂度:O(mn),其中 mm 是矩阵的行数,nn 是矩阵的列数。我们至多只需要遍历该矩阵两次。
//空间复杂度:O(1),我们只需要常数空间存储若干变量。

下附测试代码:

int main()
{
    vector<vector<int>> matrix1 = { {1, 1, 1} ,{1, 0, 1},{1, 1, 1} };
    vector<vector<int>> matrix2 = { {1, 1, 1} ,{1, 0, 1},{1, 1, 1} };
    vector<vector<int>> matrix3 = { {1, 1, 1} ,{1, 0, 1},{1, 1, 1} };
    Solution* x1 = new Solution;
    Solution1* x2 = new Solution1;
    Solution2* x3 = new Solution2;
    x1->setZeroes(matrix1);
    x2->setZeroes(matrix2);
    x3->setZeroes(matrix3);
    for (int i = 0; i < matrix1.size(); i++) {
        for (int j = 0; j < matrix1[0].size(); j++) {
            cout << matrix1[i][j] << " ";
            //cout << matrix2[i][j] << " ";
           //cout << matrix3[i][j] << " ";
            if (j == matrix1[0].size() - 1) {
                cout << endl;
            }
           
        }
    }
    system("pause");
}

测试结果:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值