[每日一题]120:矩阵置零

文章目录

    • 题目描述
      • 题目解答
        • 方法一: O ( m n ) O(mn) O(mn) 的额外空间
        • 方法二: O ( m + n ) O(m + n) O(m+n)的额外空间
        • 方法三:常数空间


题目描述

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

示例 1:

输入: 
[
  [1,1,1],
  [1,0,1],
  [1,1,1]
]
输出: 
[
  [1,0,1],
  [0,0,0],
  [1,0,1]
]

示例 2:

输入: 
[
  [0,1,2,0],
  [3,4,5,2],
  [1,3,1,5]
]
输出: 
[
  [0,0,0,0],
  [0,4,5,0],
  [0,3,1,0]
]

进阶:

一个直接的解决方案是使用 O(mn) 的额外空间,但这并不是一个好的解决方案。
一个简单的改进方案是使用 O(m + n) 的额外空间,但这仍然不是最好的解决方案。
你能想出一个常数空间的解决方案吗?

题目解答

方法一: O ( m n ) O(mn) O(mn) 的额外空间

代码实现:

class Solution{
public:
    void setZeroes(vector<vector<int>>& matrix) {
        if (matrix.empty() || matrix[0].empty()) {
            return;
        }

        int M = matrix.size();
        int N = matrix[0].size();
        vector<vector<int>> copy = matrix;

        for (int i = 0; i < M; i++) {
            for (int j = 0; j < N; j++) {
                if (rowContainsZero(i, copy) || colContainsZero(j, copy)) {
                    matrix[i][j] = 0;
                }
            }
        }
    }

private:
    bool rowContainsZero(int i, vector<vector<int>>& copy) {
        for (int j = 0; j < copy[i].size(); j++) {
            if (copy[i][j] == 0) {
                return true;
            }
        }

        return false;
    }

    bool colContainsZero(int j, vector<vector<int>>& copy) {
        for (int i = 0; i < copy.size(); i++) {
            if (copy[i][j] == 0) {
                return true;
            }
        }

        return false;
    }
};
方法二: O ( m + n ) O(m + n) O(m+n)的额外空间

代码实现:

class Solution{
public:
    void setZeroes(vector<vector<int>>& matrix){
        if (matrix.empty() || matrix[0].empty()) {
            return;
        }

        int M = matrix.size();
        int N = matrix[0].size();
        vector<bool> rowNeedToSet(M, false);
        vector<bool> colNeedToSet(N, false);

        for (int i = 0; i < M; i++) {
            for (int j = 0; j < N; j++) {
                if (matrix[i][j] == 0) {
                    rowNeedToSet[i] = true;
                    colNeedToSet[j] = true;
                }
            }
        }

        for (int i = 0; i < M; i++) {
            for (int j = 0; j < N; j++) {
                if (rowNeedToSet[i] || colNeedToSet[j]) {
                    matrix[i][j] = 0;
                }
            }
        }
    }
};
方法三:常数空间
  1. 每一行和每一列的第一个元素设置为标识位,如果为0,则标识该行或者该列存在0元素
  2. 因为第一行和第一列的元素都是matrix[0][0],令其表示第一行,所以单独设置一个flag来标识第一列的情况
  3. 要注意顺序:如果第一列有0,先对第一列所有置0的话,再对行遍历的话,会导致所有

代码实现::

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int flag = 0;
        int row = matrix.size(), col = matrix[0].size();

        for (int i = 0; i < row; ++i) {
            if (matrix[i][0] == 0) flag = 1;
            for (int j = 1; j < col; ++j) {
                if (matrix[i][j] == 0) {
                    matrix[0][j] = 0;
                    matrix[i][0] = 0;
                }
            }
        }
        // 将需要变0的列设置完毕
        for (int m = 1; m < col; ++m) {
            if (matrix[0][m] == 0) {
                for (int n = 0; n < row; ++n) {
                    matrix[n][m] = 0;
                }
            }
        }
        // 将需要变0的行设置完毕
        for (int m = 0; m < row; m++) {
            if (matrix[m][0] == 0) {
                for (int n = 0; n < matrix[0].size(); ++n) {
                    matrix[m][n] = 0;
                }
            }
        }
        // 如果需要,将第一列设置完毕
        if (flag) {
            for (int m = 0; m < row; ++m) {
                matrix[m][0] = 0;
            }
        }   
    }
};

你可能感兴趣的:(每日一题,线性表,算法)