Data structure and algorithm-4. Matrix zeroing

Posted by starter911 on Tue, 26 Oct 2021 06:21:13 +0200

4. Matrix zeroing

subject

Given a matrix of m x n, if an element is 0, all elements in its row and column are set to 0. Please use the in place algorithm.
Advanced:
An intuitive solution is to use the extra space of O (m, n), but this is not a good solution.
A simple improvement is to use the additional space of O(m + n), but this is still not the best solution.
Can you think of a solution that uses only constant space?

  • m == matrix.length
  • n == matrix[0].length
  • 1 <= m, n <= 200
  • -2^31 <= matrix[i][j] <= 2^31 - 1

4.0 violence (using a lot of extra space)

An additional two-dimensional array is used for zeroing operation, which can avoid some problems caused by zeroing the original array

void setDataZeroes(vector<vector<int>>& data, int row, int col)
{
    for (int i = 0; i < data[0].size(); i++)
        data[row][i] = 0;
    for (int i = 0; i < data.size(); i++)
        data[i][col] = 0;
}
void setZeroes0(vector<vector<int>>& matrix)
{
    int rowSize = matrix.size();
    int colSize = matrix[0].size();
    vector<vector<int>> data(rowSize, vector<int>(colSize, 1));
    for (int i = 0; i < rowSize; i++)                           //Copy a matrix to data
        for (int j = 0; j < colSize; j++)
            data[i][j] = matrix[i][j];

    for (int i = 0; i < rowSize; i++)                           //Zero data
        for (int j = 0; j < colSize; j++)
            if (matrix[i][j] == 0)
                setDataZeroes(data, i, j);

    for (int i = 0; i < rowSize; i++)                           //Copy the zeroed data to the matrix
        for (int j = 0; j < colSize; j++)
            matrix[i][j] = data[i][j];
}
  • Time complexity: O (m, n)
  • Space complexity: O (m, n)

4.1. Improving violence

Use two one-dimensional arrays, one to record which rows should be zeroed and the other to record which columns should be zeroed

void setZeroes1(vector<vector<int>>& matrix) 
{
    vector<int> data1(matrix.size(), 0);
    vector<int> data2(matrix[0].size(), 0);
    for (size_t i = 0; i < matrix.size(); i++)              //Which rows and columns of the record are all zeros
    {
        for (size_t j = 0; j < matrix[i].size(); j++)
        {
            if (matrix[i][j] == 0)
            {
                data1[i] = 1;
                data2[j] = 1;
            }
        }
    }
    for (size_t i = 0; i < data1.size(); i++)               //Zero row
    {
        if (data1[i] == 0)continue;
        for (size_t j = 0; j < matrix[0].size(); j++)
        {
            matrix[i][j] = 0;
        }
    }
    for (size_t i = 0; i < data2.size(); i++)               //Zeroing columns
    {
        if (data2[i] == 0)continue;
        for (size_t j = 0; j < matrix.size(); j++)
        {
            matrix[j][i] = 0;
        }
    }
}
  • Time complexity: O (m, n)
  • Spatial complexity: O (m + n)

4.2. Change to violence

No extra space is used to record which rows and columns should be zeroed. How to mark them? Of course, the original array is used to mark them

Suppose that the middle number of an array of 3 * 3 is 0, how to mark its position?

Setting [0,1] to zero means that the second column should be set to zero

Setting [1,0] to zero means that the second line should be set to zero

Because it is a sequential traversal, setting these two numbers to zero will not affect the judgment of setting zero as a whole

Another problem is that if the first row has zero but the first column has no zero, the first number will be set to zero, resulting in misjudgment. Therefore, two additional variables should be used to judge whether the first row and the first column are set to zero

void setZeroes3(vector<vector<int>>& matrix)
{
    bool firstRow = false,                                      //Used to mark whether the first row and column should be set to zero
    firstCol = false;
    int rowSize = matrix.size();
    int colSize = matrix[0].size();

    for (int i = 0; i < rowSize; i++)
        for (int j = 0; j < colSize; j++)                       //Mark all rows and columns that should be zeroed
            if (!matrix[i][j])
            {
                if (!i)firstRow = true;
                if (!j)firstCol = true;
                matrix[i][0] = 0;
                matrix[0][j] = 0;
            }

    for (int i = 1; i < rowSize; i++)                           //Zero the non first row and non first column first
        for (int j = 1; j < colSize; j++)
            if (!matrix[i][0] || !matrix[0][j])
                matrix[i][j] = 0;

    if (firstRow)
        for (int i = 0; i < colSize; i++)
            matrix[0][i] = 0;
    if (firstCol)
        for (int i = 0; i < rowSize; i++)
            matrix[i][0] = 0;
}
  • Time complexity: O (m, n)
  • Space complexity: O (1)

4.3 final improvement

Blogger here to explain that the above is my limit

Careful friends may find a problem. The first number of the above method is not used. If you want to be picky, you can use the first number to indicate whether the first row (or column) should be set to zero, and then use only one variable to represent another column (or row), so that the extra space is true. 1.

Topics: Algorithm data structure