题意很简单,就是把某个为0的元素所在的行和列全部归0。
要求是使空间复杂度尽可能小。
有两种写法,一种是空间复杂度O(m + n)的;一种是O(1)的。
O(m + n):
1 class Solution { 2 public void setZeroes(int[][] matrix) { 3 int m = matrix.length; 4 if (m == 0) 5 return; 6 int n = matrix[0].length; 7 Map<Integer, Boolean> rows = new HashMap<>(); 8 Map<Integer, Boolean> cols = new HashMap<>(); 9 for (int i = 0; i < m; i++) { 10 for (int j = 0; j < n; j++) { 11 if (matrix[i][j] == 0) { 12 rows.put(i, true); 13 cols.put(j, true); 14 } 15 } 16 } 17 for (int i = 0; i < m; i++) { 18 for (int j = 0; j < n; j++) { 19 if (rows.containsKey(i) || cols.containsKey(j)) { 20 matrix[i][j] = 0; 21 } 22 } 23 } 24 } 25 }
这是我最开始想的方法,即利用一个额外的关联数组(Map, Set实现都可以)记录哪些行和列需要归零。
O(1):
1 class Solution { 2 public void setZeroes(int[][] matrix) { 3 int m = matrix.length; 4 if (m == 0) 5 return; 6 int n = matrix[0].length; 7 8 boolean resetFirstRow = false; 9 boolean resetFirstCol = false; 10 11 for (int i = 0; i < m; i++) { 12 for (int j = 0; j < n; j++) { 13 if (matrix[i][j] == 0) { 14 resetFirstRow = i == 0 ? true : resetFirstRow; 15 resetFirstCol = j == 0 ? true : resetFirstCol; 16 matrix[i][0] = 0; 17 matrix[0][j] = 0; 18 } 19 } 20 } 21 //将除了第一行和第一列外的其他部分归零 22 for (int i = 1; i < m; i++) { 23 for (int j = 1; j < n; j++) { 24 if (matrix[i][0] == 0 || matrix[0][j] == 0) { 25 matrix[i][j] = 0; 26 } 27 } 28 } 29 //将第一行归零 30 if (resetFirstRow) { 31 for (int j = 0; j < n; j++) 32 matrix[0][j] = 0; 33 } 34 //将第一列归零 35 if (resetFirstCol) { 36 for (int i = 0; i < m; i++) 37 matrix[i][0] = 0; 38 } 39 } 40 }
这个方法最强的地方是它直接利用第一行和第一列作为桶来记录该行/列是否需要归零,效果和使用关联数组完全一致。
不过这样做可能会对第一行/列进行改动,所以需要两个布尔类型的变量来判断第一行/列是否真的需要归零。
代码中第14 ~ 17行的写法比较巧妙,总是先判断第一行/列的某个元素,然后再修改它。因此改动不会影响我们的判断。
当然如果按最最最保险的方法的写,可以将第一行,第一列和剩下的部分分开单独判断,稍微麻烦一点。
总结:
1. 可以利用已有数组的一部分记录信息,从而避免引入额外的数据结构(空间)。