[73] leetcode zero matrix (array, in-place algorithm)

Topic links: https://leetcode-cn.com/problems/set-matrix-zeroes/

Title Description

Given an mxn matrix, if one element is zero, then all elements of its row and column are set to 0. Use the in-situ method.

Example 1:

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

Example 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]
]

Advanced:

  • A direct solution is to use O (mn) additional space, but this is not a good solution.
  • A simple improvement is to use O (m + n) additional space, but this is still not the best solution.
    Can you think of a solution constant space it?

Thinking

In-place algorithm requires space complexity is O (1), start with the idea of ​​non-in-place algorithm, and then place proposed algorithm.

1 O (mn)

Traversed twice matrix
(1) The first time through, a two-dimensional array with a recording element needs to be set to zero
(2) corresponding to the position of the second pass element zeroing

Complexity Analysis
time complexity: O (mn (m + n ))
space complexity: O (mn)

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        if(matrix.empty() || matrix[0].empty())
            return;
        int rows = matrix.size(), cols = matrix[0].size();
        vector<vector<bool>> flag(rows, vector<bool>(cols,false));
        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                if(matrix[i][j] == 0){
                    // 标记同一行非0元素
                    for (int k = 0; k < cols; ++k)
                        if(matrix[i][k]!=0)
                            flag[i][k] = true;
                    // 标记同一列非0元素
                    for (int k = 0; k < rows; ++k)
                        if(matrix[k][j]!=0)
                            flag[k][j] = true;
                }
            }
        }
        // 置零
        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                if(flag[i][j])
                    matrix[i][j] = 0;
            }
        }
    }
};

Here Insert Picture Description

2 O(m+n)

Because the requirements are all 0 All ranks are set to 0, so we only need to record the row and column number 0 is located, the second set when traversing zero
complexity analysis
time complexity: O (mn)
space complexity : O (m + n)

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        if(matrix.empty() || matrix[0].empty())
            return;
        int rows = matrix.size(), cols = matrix[0].size();
        vector<vector<bool>> flag(rows, vector<bool>(cols,false));
        set<int> rowSet, colSet;
        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                if(matrix[i][j] == 0){
                    rowSet.insert(i);
                    colSet.insert(j);
                }
            }
        }
        // 置零
        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                if(rowSet.count(i)!=0 || colSet.count(j)!=0)
                    matrix[i][j] = 0;
            }
        }
    }
};

Here Insert Picture Description

3 O (1) in-place algorithm

[Tricky approach / fail]
(1) again to traverse the matrix, the other element is present 0 0 Non-element is set to row / column is a flag value as the INT
_Min
(2) traversing a second pass matrix, all flag values are set to 0

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        if(matrix.empty() || matrix[0].empty())
            return;
        int rows = matrix.size(), cols = matrix[0].size();
        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                if(matrix[i][j] == 0){
                    // 同一行非0设为INT_MIN
                    for (int k = 0; k < cols; ++k)
                        if(matrix[i][k]!=0)
                            matrix[i][k] = INT_MIN;
                    // 同一列非0设为INT_MIN
                    for (int k = 0; k < rows; ++k)
                        if(matrix[k][j]!=0)
                            matrix[k][j] = INT_MIN;
                }
            }
        }
        // 将所有INT_MIN置为0
        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                if(matrix[i][j] == INT_MIN){
                    matrix[i][j] = 0;
                }
            }
        }
    }
};

Test will contain an error flag value. .
Here Insert Picture Description

[] The right way

/*
 * 利用数组的首行和首列来记录0值,相当于上一方法的set
 * 从数组下标的A[1][1]开始遍历,额外两个布尔变量标记首行首列是否需要置零
 * 时间复杂度O(mn)
 * 空间复杂度O(1)
 */
class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        if(matrix.empty() || matrix[0].empty())
            return;
        int rows = matrix.size(), cols = matrix[0].size();
        bool rowFlag = false, colFlag = false;
        // 检查首行是否需要置零
        for (int j = 0; j < cols; ++j){
            if(matrix[0][j] == 0){
                rowFlag = true;
                break;
            }
        }
        // 检查首列是否需要置零
        for (int i = 0; i < rows; ++i) {
            if(matrix[i][0] == 0){
                colFlag = true;
                break;
            }
        }

        for (int i = 1; i < rows; ++i) {
            for (int j = 1; j < cols; ++j) {
                if(matrix[i][j] == 0){
                    matrix[i][0] = 0;
                    matrix[0][j] = 0;
                }
            }
        }

        // 将上面标记的行列置为0
        for (int i = 1; i < rows; ++i) {
            for (int j = 1; j < cols; ++j) {
                if(matrix[i][0] == 0 || matrix[0][j] == 0)
                    matrix[i][j] = 0;
            }
        }
        // 首行置零
        if(rowFlag){
            for (int j = 0; j < cols; ++j)
                matrix[0][j] = 0;
        }
        // 首列置零
        if(colFlag){
            for (int i = 0; i < rows; ++i)
                matrix[i][0] = 0;
        }
    }
};

Here Insert Picture Description

Guess you like

Origin blog.csdn.net/zjwreal/article/details/94594799