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

示例 1:

输入: 
[
  [1,1,1],
  [1,0,1],
  [1,1,1]
]
输出: 
[
  [1,0,1],
  [0,0,0],
  [1,0,1]
]
示例 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]
]
进阶:

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

 

思路:

就是使用标记的问题

     //O(m+n)的時間复杂度
	 public void setZeroes1(int[][] matrix) {
		    int m = matrix.length;
	        int n = matrix[0].length;
	        boolean[] rawFlags = new boolean[m];  //标记该行有0
	        boolean[] colFlags = new boolean[n];  //标记该列有0
	        for (int i = 0; i < m; i++) {
	            for (int j = 0; j < n; j++) {
	                if (matrix[i][j] == 0) {
	                    rawFlags[i] = true;
	                    colFlags[j] = true;
	                }
	            }
	        }
	        // 调整每一行置0
	        for (int i = 0; i < m; i++) {
	            if (rawFlags[i]) {
	                for (int j = 0; j < n; j++) {
	                    matrix[i][j] = 0;
	                }
	            }
	        }
	        // 调整每一列置0
	        for (int i = 0; i < n; i++) {
	            if (colFlags[i]) {
	                for (int j = 0; j < m; j++) {
	                    matrix[j][i] = 0;
	                }
	            }
	        }     
    }

使用常数空间的解法

     //O(1)空间复杂度 用每一行的第一列作为标记
	 public void setZeroes(int[][] matrix) {
		 int col0 = 1;      //记录第一列 
		 int m = matrix.length, n = matrix[0].length;

	        for (int i = 0; i < m; i++) {
	            if (matrix[i][0] == 0) col0 = 0;  //标记第一列是否为0
	            for (int j = 1; j < n; j++)       //从第二列开始
	                if (matrix[i][j] == 0)
	                    matrix[i][0] = matrix[0][j] = 0;
	        }

	        for (int i = m - 1; i >= 0; i--) {
	            for (int j = n - 1; j >= 1; j--)  {   //判断到第二列
	                if (matrix[i][0] == 0 || matrix[0][j] == 0)
	                    matrix[i][j] = 0;
	            }
	            if (col0 == 0) matrix[i][0] = 0;
	        }
	 }