Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LeetCode] 73. Set Matrix Zeroes #73

Open
grandyang opened this issue May 30, 2019 · 0 comments
Open

[LeetCode] 73. Set Matrix Zeroes #73

grandyang opened this issue May 30, 2019 · 0 comments

Comments

@grandyang
Copy link
Owner

grandyang commented May 30, 2019


请点击下方图片观看讲解视频
Click below image to watch YouTube Video
Video

Given an m x n integer matrix matrix, if an element is 0, set its entire row and column to 0's.

You must do it in place.

Example 1:

Input: matrix = [[1,1,1],[1,0,1],[1,1,1]]
Output: [[1,0,1],[0,0,0],[1,0,1]]

Example 2:

Input: matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]
Output: [[0,0,0,0],[0,4,5,0],[0,3,1,0]] 

Constraints:

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

Follow up:

  • A straightforward solution using O(mn) space is probably a bad idea.
  • A simple improvement uses O(m + n) space, but still not the best solution.
  • Could you devise a constant space solution?

据说这题是 CareerCup 上的原题,也不算难,虽然博主也是看了网上的解法照着写的,但是下次遇到绝对想的起来。这道题中说的空间复杂度为 O(mn) 的解法自不用多说,直接新建一个和 matrix 等大小的矩阵,然后一行一行的扫,只要有0,就将新建的矩阵的对应行全赋0,行扫完再扫列,然后把更新完的矩阵赋给 matrix 即可,这个算法的空间复杂度太高。将其优化到 O(m+n) 的方法是,用一个长度为m的一维数组记录各行中是否有0,用一个长度为n的一维数组记录各列中是否有0,最后直接更新 matrix 数组即可。这道题的要求是用 O(1) 的空间,那么就不能新建数组,就用原数组的第一行第一列来记录各行各列是否有0.

- 先扫描第一行第一列,如果有0,则将各自的 flag 设置为 true
- 然后扫描除去第一行第一列的整个数组,如果有0,则将对应的第一行和第一列的数字赋0
- 再次遍历除去第一行第一列的整个数组,如果对应的第一行和第一列的数字有一个为0,则将当前值赋0
- 最后根据第一行第一列的 flag 来更新第一行第一列

解法一:

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int m = matrix.size(), n = matrix[0].size();
        bool rowZero = false, colZero = false;
        for (int i = 0; i < m; ++i) {
            if (matrix[i][0] == 0) colZero = true;
        }
        for (int i = 0; i < n; ++i) {
            if (matrix[0][i] == 0) rowZero = true;
        } 
        for (int i = 1; i < m; ++i) {
            for (int j = 1; j < n; ++j) {
                if (matrix[i][j] == 0) {
                    matrix[0][j] = 0;
                    matrix[i][0] = 0;
                }
            }
        }
        for (int i = 1; i < m; ++i) {
            for (int j = 1; j < n; ++j) {
                if (matrix[0][j] == 0 || matrix[i][0] == 0) {
                    matrix[i][j] = 0;
                }
            }
        }
        if (rowZero) {
            for (int i = 0; i < n; ++i) matrix[0][i] = 0;
        }
        if (colZero) {
            for (int i = 0; i < m; ++i) matrix[i][0] = 0;
        }
    }
};

我们可以稍微优化一下上面的解法,少用几个 for 循环,这里只用一个变量 colZero 来表示首列是否有0存在即可,首行不用单独去记录,因为其是否为0会在 matrix[0][0] 中记录。这里只需要两个嵌套 for 循环就可以了,第一个嵌套 for 循环的i是从0开始遍历的,若首列有0,则将 colZero 标记为 true。内层 for 循环的j是从1开始遍历的,若 matrix[i][j] 为0了,则将 matrix[0][j] 和 matrix[i][0] 都赋值为0。然后开始第二个嵌套 for 循环,外层的 for 循环的i是从 m-1 往前遍历到0,内层的 for 循环的j是从 n-1 往前遍历到1,若 matrix[0][j] 和 matrix[i][0] 中任意一个为0了,则将 matrix[i][j] 赋值为0,同时在外层 for 循环的遍历过程中,判断若 colZero 为 true,则将 matrix[i][0] 赋值为0,这就保证了首列被更新了,参见代码如下:

解法二:

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int m = matrix.size(), n = matrix[0].size();
        bool colZero = false;
        for (int i = 0; i < m; ++i) {
            if (matrix[i][0] == 0) colZero = true;
            for (int j = 1; j < n; ++j) {
                if (matrix[i][j] == 0) {
                    matrix[0][j] = 0;
                    matrix[i][0] = 0;
                }
            }
        }
        for (int i = m - 1; i >= 0; --i) {
            for (int j = n - 1; j >= 1; --j) {
                if (matrix[0][j] == 0 || matrix[i][0] == 0) {
                    matrix[i][j] = 0;
                }
            }
            if (colZero) matrix[i][0] = 0;
        }
    }
};

Github 同步地址:

#73

类似题目:

Game of Life

Number of Laser Beams in a Bank

Minimum Operations to Remove Adjacent Ones in Matrix

Remove All Ones With Row and Column Flips II

参考资料:

https://leetcode.com/problems/set-matrix-zeroes/

https://leetcode.com/problems/set-matrix-zeroes/solutions/26014/any-shorter-o-1-space-solution/

LeetCode All in One 题目讲解汇总(持续更新中...)

(欢迎加入博主的知识星球,博主将及时答疑解惑,并分享刷题经验与总结,快快加入吧~)

知识星球 喜欢请点赞,疼爱请打赏❤️~.~

微信打赏

|

Venmo 打赏


---|---

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant