Hot100-Day05-T73矩阵置零

0 阅读4分钟

Day05[26/3/5]T73.矩阵置零

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

示例 1:

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

示例 2:

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

提示:

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

进阶:

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

解题思路

首先想到:创建两个 set(集合,也就是元素不能重复且排序的数组)

扫描所有的 0 元素,把每个元素的行号和列号各自记录到一个 set 里

最后,根据这两个 set 把指定行和列全部置零就可以了 。

优化:这里空间复杂度是 O(m+n)

你不用非要创建两个 set,你把这个矩阵的第 0 行和第 0 列就当作是 set 就可以了,

比如说,data[a][b] = 0,那么把 data[a][0] 和 data[0][b] 都置为 0 不就行了,

最后去检查第 0 行和第 0 列哪些元素为 0,再把相应行和列置零就可以了。

注意:

置零的时候考虑 data[0][0]==0时,你先扫描行,会导致第 0 列全 0,然后你再扫描列的时候,就会把所有行都置零,导致整个矩阵全 0。先扫描列也是同理。所以应该在开始时避开这个元素,最后单独处理这个元素。

扫描的时候也会有类似的问题,也请考虑。

(本质就是 [0][0] 位置上的 0,你不确定是代表,这一行需要置零,还是这一列需要置零,还是行列都需要置零,所以需要引入标志位来做出区分)

Code

#include <iostream>
using namespace std;

#include <vector>
#include <algorithm>

class Solution
{
public:
    void setZeroes(vector<vector<int>> &matrix)
    {
        // step.1 扫描0元素
        // 为了避免[0][0]不确定是指行0还是列0还是行列均0
        // 先考虑第0行第0列本身有无0,然后排除第0行和第0列进行扫描
        int flag00 = 0;
        if (matrix[0][0] == 0)
        {
            // 行列都要置零
            flag00 = 2;
        }
        else
        {
            // 扫描0行
            for (int j = 0; j < matrix[0].size(); j++)
            {
                if (matrix[0][j] == 0)
                {
                    // 1 表示第0行需要置零
                    flag00 = 1;
                    break;
                }
            }
            // 扫描0列
            for (int i = 0; i < matrix.size(); i++)
            {
                if (matrix[i][0] == 0)
                {
                    if (flag00 == 0)
                    {
                        // -1 只有列需要置零
                        flag00 = -1;
                    }
                    else
                    {
                        // 2 行列都需要置零
                        flag00 = 2;
                    }
                    break;
                }
            }
        }

        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] = 0;
                    matrix[0][j] = 0;
                }
            }
        }

        // step.2 置零
        // 一定要考虑到matrix[0][0]==0时会导致全0
        // 所以两次搜索都避开[0][0]
        // 第0列扫描,先找出需要置零的行(避开[0][0])
        for (int i = 1; i < matrix.size(); i++)
        {
            if (matrix[i][0] == 0)
            {
                // 不用从0列开始
                for (int j = 1; j < matrix[0].size(); j++)
                {
                    matrix[i][j] = 0;
                }
            }
        }

        // 第0行扫描,找出要置零的列(避开[0][0])
        for (int j = 1; j < matrix[0].size(); j++)
        {
            if (matrix[0][j] == 0)
            {
                // 不用处理第0行
                for (int i = 1; i < matrix.size(); i++)
                {
                    matrix[i][j] = 0;
                }
            }
        }

        // 单独处理[0][0]
        // 行置零
        if (flag00 == 1 || flag00 == 2)
        {
            for (int j = 0; j < matrix[0].size(); j++)
            {
                matrix[0][j] = 0;
            }
        }
        // 列置零
        if (flag00 == -1 || flag00 == 2)
        {
            for (int i = 0; i < matrix.size(); i++)
            {
                matrix[i][0] = 0;
            }
        }
    }
};

int main()
{

    // vector<vector<int>> matrix = {
    //     {1, 1, 1},
    //     {1, 0, 1},
    //     {1, 1, 1},
    // };
    // 答案 [[1,0,1],[0,0,0],[1,0,1]]

    vector<vector<int>> matrix = {
        {0, 1, 2, 0},
        {3, 4, 5, 2},
        {1, 3, 1, 5},
    };
    // 答案 [[0,0,0,0],[0,4,5,0],[0,3,1,0]]

    // vector<vector<int>> matrix = {
    //     {0, 1, 2, 0},
    //     {3, 4, 5, 2},
    //     {1, 3, 1, 5},
    //     {0, 3, 1, 5},
    //     {1, 3, 1, 5},
    // };
    // 测试

    // vector<vector<int>> matrix = {
    //     {1, 0}};

    // vector<vector<int>> matrix = {
    //     {1, 2, 3, 4},
    //     {5, 0, 7, 8},
    //     {0, 10, 11, 12},
    //     {13, 14, 15, 0},
    // };

    // vector<vector<int>> matrix = {
    //     {-4, -2147483648, 6, -7, 0},
    //     {-8, 6, -8, -6, 0},
    //     {2147483647, 2, -9, -6, -10},

    // };

    Solution sol;
    sol.setZeroes(matrix);

    cout << endl;
    for (int i = 0; i < matrix.size(); i++)
    {
        cout << "[";
        for (int j = 0; j < matrix[0].size(); j++)
        {
            cout << matrix[i][j] << ",";
        }
        cout << "]" << endl;
    }

    return 0;
}