【Leetcode】73. Set Matrix Zeroes

题目地址:

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

给定一个矩阵,将其中的含有 0 0 的行和列全部置零。

法1:容易想到的方法是,用一个数据结构来记录哪些行和哪些列需要置零,最后统一置零即可。此处可以用两个哈希表。代码如下:

import java.util.Arrays;
import java.util.HashSet;

public class Solution {
    public void setZeroes(int[][] matrix) {
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return;
        }
        // rows记录哪些行需要置零,cols记录哪些列需要置零
        HashSet<Integer> rows = new HashSet<>(), cols = new HashSet<>();
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
                if (matrix[i][j] == 0){
                    rows.add(i);
                    cols.add(j);
                }
            }
        }
    	
    	// 最后统一置零
        for (Integer row : rows) {
            Arrays.fill(matrix[row], 0);
        }
        for (Integer col : cols) {
            for (int i = 0; i < matrix.length; i++) {
                matrix[i][col] = 0;
            }
        }
    }
}

时间复杂度 O ( m n ) O(mn) ,空间复杂度 O ( m + n ) O(m+n) m m n n 分别为行数和列数。

法2:如果不用额外空间的话,直观的想法是,直接用原矩阵来记录需要置零的行或者列这个信息。比如,我们可以对每一个需要置零的行和列的第一个元素来做标记,之后在update矩阵的时候,就check一下当前行或者列是否做了标记,如果做了标记就置零,否则就跳过。之后还需要check一下第一行和第一列是否需要置零。代码如下:

import java.util.Arrays;

public class Solution {
    public void setZeroes(int[][] matrix) {
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return;
        }
        
    	// 标记第0行和第0列是否需要置零
        boolean row0 = false, col0 = false;
        for (int j = 0; j < matrix[0].length; j++) {
            if (matrix[0][j] == 0) {
                row0 = true;
                break;
            }
        }
    
        for (int i = 0; i < matrix.length; i++) {
            if (matrix[i][0] == 0) {
                col0 = true;
                break;
            }
        }
    
    	// 接下来开始利用第0行和第0列来记录本行或者本列最终是否需要置零
        for (int i = 1; i < matrix.length; i++) {
            for (int j = 1; j < matrix[0].length; j++) {
                if (matrix[i][j] == 0) {
                    matrix[i][0] = 0;
                    matrix[0][j] = 0;
                }
            }
        }
        
    	// 利用标记的信息来置零
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
                if (matrix[i][0] == 0 || matrix[0][j] == 0) {
                    matrix[i][j] = 0;
                }
            }
        }
        
        // 最后更新第0行和第0列
        if (row0) {
            Arrays.fill(matrix[0], 0);
        }
        if (col0) {
            for (int i = 0; i < matrix.length; i++) {
                matrix[i][0] = 0;
            }
        }
    }
}

时间复杂度一样,空间 O ( 1 ) O(1)

算法正确性证明:
先想象原矩阵除去第 0 0 行和第 0 0 列构成的矩阵,我们只把第 0 0 行和第 0 0 列当成标记用途的行,那么接下来遍历剩下的矩阵的时候,就可以利用那两行做标记,很显然剩下的矩阵中某个位置置零,当且仅当它的所在行或者所在列被做过标记。接下来再更新第 0 0 行和第 0 0 列即可。

发布了125 篇原创文章 · 获赞 0 · 访问量 6639

猜你喜欢

转载自blog.csdn.net/qq_46105170/article/details/104106710
今日推荐