# 73. Set Matrix Zeroes

**<font color=red>难度: Meidum</font>**

## 刷题内容

> 原题连接

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

> 内容描述

```
Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in-place.

Example 1:

Input: 
[
  [1,1,1],
  [1,0,1],
  [1,1,1]
]
Output: 
[
  [1,0,1],
  [0,0,0],
  [1,0,1]
]
Example 2:

Input: 
[
  [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]
]
Follow up:

A straight forward 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?
```

## 解题方案

> 思路 1
******- 时间复杂度: O(row * col * (row + col))******- 空间复杂度: O(row * col)******

Naive AC代码，直接复制一份matrix，边遍历边改,beats 64.75%

```python
class Solution(object):
    def setZeroes(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: void Do not return anything, modify matrix in-place instead.
        """
        def setZero(i,j):
            for m in range(col):
                matrix[i][m] = 0
            for n in range(row):
                matrix[n][j] = 0
        
        row = len(matrix)
        col = len(matrix[0]) if row else 0
        new_matrix = [matrix[i][:] for i in range(row)]
        
        for i in range(row):
            for j in range(col):
                if new_matrix[i][j] == 0:
                    setZero(i,j)
```


> 思路 2
******- 时间复杂度: O(row * col)******- 空间复杂度: O(row * col)******


一边遍历，一边将相应的行和列置为0是行不通的，会影响后面元素的遍历判断，

稍微优化一下空间，我们只需要记录下最后需要置为0的行index和列index即可,beats 80.11%，时间上也得到了优化


```python
class Solution:
    def setZeroes(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: void Do not return anything, modify matrix in-place instead.
        """        
        row = len(matrix)
        col = len(matrix[0]) if row else 0
        rows, cols = set(), set()
        
        for i in range(row):
            for j in range(col):
                if matrix[i][j] == 0:
                    rows.add(i)
                    cols.add(j)
                    
        for i in range(row):
            for j in range(col):
                if i in rows or j in cols:
                    matrix[i][j] = 0
```

> 思路 3
******- 时间复杂度: O(row * col * (row + col))******- 空间复杂度: O(1)******

继续优化空间，我们发现可以换一种方式把最后需要置为0的点记录下来，那就是将那个点的值先设为一个特殊值sign，
最后再来一次遍历，只要值为sign的点都置为0即可，beats 64.75%

```python
class Solution:
    def setZeroes(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: void Do not return anything, modify matrix in-place instead.
        """
        sign = -sys.maxsize
        row = len(matrix)
        col = len(matrix[0]) if row else 0
        
        for i in range(row):
            for j in range(col):
                if matrix[i][j] == 0:
                    # 把所有最后需要置为0的点先置为sign
                    for k in range(col):
                        matrix[i][k] = sign if matrix[i][k] != 0 else 0
                    for k in range(row):
                        matrix[k][j] = sign if matrix[k][j] != 0 else 0
                        
        for i in range(row):
            for j in range(col):
                # 把所有值为sign的点全部置为0
                if matrix[i][j] == sign:
                    matrix[i][j] = 0
```



> 思路 4
******- 时间复杂度: O(row * col)******- 空间复杂度: O(1)******

我们现在可以在思路3的基础上优化时间了，其实我们不需要记录下每一个最后需要置为0的点，而是记录下他们对应的行inde和列index就可以了，
这里用一个小trick，我们只需要将该行和该列的首元素变为0即可，第二次遍历的时候，只要一个点所处的行或者列的首元素是0，那么就将这个点置为0，

最后chekc一下第一行和第一列，不管matrix[0][0]是一开始就是0还是后面我们将它置为0的，第一行肯定都要全部置为0

对于第一列来说，我们只要之前有过一个元素在其中是0的话，整个列就需要全部置为0，之所以先check第一行再check第一列，是为了防止在这个check中将matrix[0][0]置为0了


beats 94.93%

```python
class Solution:
    def setZeroes(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: void Do not return anything, modify matrix in-place instead.
        """        
        row = len(matrix)
        col = len(matrix[0]) if row else 0
        
        set_first_col = False
        for i in range(row):
            if matrix[i][0] == 0:
                set_first_col = True
            for j in range(1, col):
                if matrix[i][j] == 0:
                    matrix[i][0] = 0
                    matrix[0][j] = 0
                        
        for i in range(1, row):
            for j in range(1, col):
                if matrix[i][0] == 0 or matrix[0][j] == 0:
                    matrix[i][j] = 0
         
        if matrix[0][0] == 0:
            for j in range(col):
                matrix[0][j] = 0
                    
        if set_first_col: # 最后才判断第一列是为了防止在这个check中将matrix[0][0]置为0了
            for i in range(row):
                matrix[i][0] = 0
```





