面试题 01.08. 零矩阵
如果直接开始for循环,遇到一个0就清空对应的行和列,那么最终会导致矩阵多出很多0(原本不是0的位置,遍历到的时候也被计为0)
第一种方法
可以使用辅助矩阵:遍历矩阵的过程中,遇到一个0,就把它对应的行和列记入辅助矩阵(boolean类型)中,遍历结束后,根据辅助矩阵的值来对原矩阵进行改造。这种思路比较简单,代码也很好实现,但是它的空间复杂度为 O(MN)。
第二种方法
那么我们就需要想一种对自身进行操作的方法,不需要辅助矩阵。我们可以使用第一行和第一列来记录是否存在0点。但是问题就是:如果第一行和第一列也存在0点,这样记录会被覆盖。因此我们需要用两个boolean变量来记录第一行和第一列是否存在零点,最后记录完成后再进行改造,改造的具体方法是:行和列分别从1开始遍历(因为第一行和第一列单独处理),如果对应的第一列或第一行为0,那么就清空对应对应行/列,注意行和列的清空是相反的。
class Solution { public void setZeroes(int[][] matrix) { boolean ifRow=false,ifCol=false; //记录第一行和第一列是否有零 int m = matrix.length, n = matrix[0].length; for(int i=0;i<m;i++){ //遍历第一列 if(matrix[i][0]==0){ ifCol = true; } } for(int i=0;i<n;i++){ if(matrix[0][i]==0){ ifRow = true; } } //记录完毕,接下来遍历矩阵 for(int i=0;i<m;i++){ for(int j=0;j<n;j++){ if(matrix[i][j]==0){ //用第一行和第一列记录 matrix[0][j]=0; matrix[i][0]=0; } } } //从1开始(因为第一行和第一列要单独处理) for(int i=1;i<m;i++){ if(matrix[i][0]==0){ for(int j=1;j<n;j++){ matrix[i][j]=0; } } } for(int i=1;i<n;i++){ if(matrix[0][i]==0){ for(int j=1;j<m;j++){ matrix[j][i]=0; } } } if(ifRow){ //第一行原本就有0 for(int i=0;i<n;i++) matrix[0][i]=0; } if(ifCol){ //第一列原本就有0 for(int i=0;i<m;i++) matrix[i][0]=0; } } }