LeetCode高频题73. 矩阵置零

LeetCode高频题73. 矩阵置零

提示:本题是系列LeetCode的150道高频题,你未来遇到的互联网大厂的笔试和面试考题,基本都是从这上面改编而来的题目
互联网大厂们在公司养了一大批ACM竞赛的大佬们,吃完饭就是设计考题,然后去考应聘人员,你要做的就是学基础树结构与算法,然后打通任督二脉,以应对波云诡谲的大厂笔试面试题!
你要是不扎实学习数据结构与算法,好好动手手撕代码,锻炼解题能力,你可能会在笔试面试过程中,连题目都看不懂!比如华为,字节啥的,足够让你读不懂题
在这里插入图片描述


文章目录

  • LeetCode高频题73. 矩阵置零
    • @[TOC](文章目录)
  • 题目
  • 一、审题
  • 最简单的就是外部辅助空间记录哪些行和列,需要变0
  • 题目说了用:原地算法 搞
  • 总结

题目

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


一、审题

示例:1
LeetCode高频题73. 矩阵置零_第1张图片
输入:matrix = [[1,1,1],[1,0,1],[1,1,1]]
输出:[[1,0,1],[0,0,0],[1,0,1]]

LeetCode高频题73. 矩阵置零_第2张图片
输入:matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]
输出:[[0,0,0,0],[0,4,5,0],[0,3,1,0]]

提示:

m == matrix.length
n == matrix[0].length
1 <= m, n <= 200
-231 <= matrix[i][j] <= 231 - 1

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/set-matrix-zeroes
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


最简单的就是外部辅助空间记录哪些行和列,需要变0

当然,你遍历过程中,遇到0,不能立马改整行和整列,否则你待会不知道遇到的0是怎么来的

用一个行哈希表,列哈希表,记录哪些行,哪些列应该直接变零
耗费额外空间的

代码也很简单

        //复习:
        public void setZeroesReview(int[][] matrix) {
            if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return;

            int N = matrix.length;
            int M = matrix[0].length;

            //辅助
            HashSet<Integer> rowSet = new HashSet<>();
            HashSet<Integer> columnSet = new HashSet<>();

            //遍历
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < M; j++) {
                    if (matrix[i][j] == 0){
                        rowSet.add(i);
                        columnSet.add(j);
                    }
                }
            }

            //再修改
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < M; j++) {
                    if (rowSet.contains(i)) matrix[i][j] = 0;
                    if (columnSet.contains(j)) matrix[i][j] = 0;
                }
            }
        }

测试;

    public static void test(){
        Solution solution = new Solution();
        int[][] arr = {
                {1,1,2,4},
                {3,1,5,2},
                {0,3,1,1},
                {1,3,1,0}};
        solution.setZeroes(arr);
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[0].length; j++) {
                System.out.print(arr[i][j] +" ");
            }
            System.out.println();
        }

        System.out.println();
        int[][] arr2 = {
                {1,1,2,4},
                {3,1,5,2},
                {0,3,1,1},
                {1,3,1,0}};
        solution.setZeroesReview(arr2);
        for (int i = 0; i < arr2.length; i++) {
            for (int j = 0; j < arr2[0].length; j++) {
                System.out.print(arr2[i][j] +" ");
            }
            System.out.println();
        }

    }

    public static void main(String[] args) {
        test();
    }

结果:

0 1 2 0 
0 1 5 0 
0 0 0 0 
0 0 0 0 

0 1 2 0 
0 1 5 0 
0 0 0 0 
0 0 0 0 

LeetCode测试:
LeetCode高频题73. 矩阵置零_第3张图片
LeetCode高频题73. 矩阵置零_第4张图片

外部辅助首先耗费空间
其次时间也挺慢

题目说了用:原地算法 搞

咱们来一波节约空间和时间的做法

我们想干啥呢??
用第0行来记录,这一行,是否要整体变0???
用第0列来记录,这一列,是否要整体变0???
LeetCode高频题73. 矩阵置零_第5张图片

如果遍历过程中,发现某一行i需要变0,那i行0列这个格子就要记录
如果遍历过程中,发现某一列j需要变0,那0行j列这个格子就要记录

那注意了
你万一第0行,需要整体变0,怎么记录,单独拿一个变量row0来记录,
你万一第0列,需要整体变0,怎么记录,单独拿一个变量column0来记录,

咱们一开始就先遍历0行,如果遇到0,row0=true
咱们一开始就先遍历0列,如果遇到0,column0=true
LeetCode高频题73. 矩阵置零_第6张图片
然后遍历i=1–N-1行,遍历j=1–M-1列,用第0行和0列记录
用0记录,回头你检查,不是0的都不要动,是0的整行,或者整列都得变0

然后变的时候,当然是根据0行和0列先搞0–N-1行和0–M-1列【注意这可是整个矩阵的行列都变哦】
然后检查row0和column0,决定整个0行和0列要不要变

这就是原地算法的意思
手撕代码:

        //如果遍历过程中,发现某一行i需要变0,那i行0列这个格子就要记录
        //如果遍历过程中,发现某一列j需要变0,那0行j列这个格子就要记录
        public void setZeroesSource(int[][] matrix) {
            if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return;

            int N = matrix.length;
            int M = matrix[0].length;

            //俩变量记录
            //咱们一开始就先遍历0行,如果遇到0,row0=true
            //咱们一开始就先遍历0列,如果遇到0,column0=true
            boolean row0 = false;
            boolean column0 = false;
            for (int i = 0; i < N; i++) {
                if (matrix[i][0] == 0) column0 = true;
            }
            for (int j = 0; j < M; j++) {
                if (matrix[0][j] == 0) row0 = true;
            }
            //然后遍历i=1--N-1行,遍历j=1--M-1列,用第0行和0列记录
            //用2记录,回头你检查,不是2的都不要动,是2的整行,或者整列都得变0
            for (int i = 1; i < N; i++) {
                for (int j = 1; j < M; j++) {
                    if (matrix[i][j] == 0) {
                        matrix[i][0] = 0;
                        matrix[0][j] = 0;//对应俩格子记录0,代表这一行,这一列都得是0
                    }
                }
            }

            //然后变的时候,当然是根据0行和0列先搞1--N-1行和1--M-1列
            //然后检查row0和column0,决定整个0行和0列要不要变
            for (int i = 1; i < N; i++) {
                for (int j = 1; j < M; j++) {
                    if (matrix[i][0] == 0) matrix[i][j] = 0;//这一行都得是0
                    if (matrix[0][j] == 0) matrix[i][j] = 0;//这一列都得是0
                }
            }
            if (row0)
                for (int j = 0; j < M; j++) {
                    matrix[0][j] = 0;
                }
            if (column0)
                for (int i = 0; i < N; i++) {
                    matrix[i][0] = 0;
                }
        }

测试

        System.out.println();
        int[][] arr3 = {
                {1,1,2,4},
                {3,1,5,2},
                {0,3,1,1},
                {1,3,1,0}};
        solution.setZeroesSource(arr3);
        for (int i = 0; i < arr3.length; i++) {
            for (int j = 0; j < arr3[0].length; j++) {
                System.out.print(arr3[i][j] +" ");
            }
            System.out.println();
        }

很OK

0 1 2 0 
0 1 5 0 
0 0 0 0 
0 0 0 0 

LeetCode测试:
LeetCode高频题73. 矩阵置零_第7张图片
LeetCode高频题73. 矩阵置零_第8张图片
看看,整个空间,直接就大大地优化了

不过速度咋还慢呢???
不管,因为LeetCode有时候记录时间就是不准的,这已经是最好的算法了。


总结

提示:重要经验:

1)用辅助空间势必耗费额外空间
2)这种记录要变0或者1的事,可以原地记录,简单几个变量就行
3)笔试求AC,可以不考虑空间复杂度,但是面试既要考虑时间复杂度最优,也要考虑空间复杂度最优。

你可能感兴趣的:(大厂面试高频题之数据结构与算法,leetcode,矩阵,矩阵置零,遇到0,整行整列变0,原地算法)