Set Matrix Zeroes

来源:互联网 发布:北大青鸟怎么样知乎 编辑:程序博客网 时间:2024/06/02 04:33

题目地址:https://leetcode.com/submissions/detail/130756933/

Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place.

这个题目的关键就在于不要让修改后的0“传染”给其他行列,所以我们可以这么想:如果提前把0元素所在的行列坐标存储起来,然后再去置0不就可以了吗?比如我们可以存储在一个HashMap中,key作为行坐标,value可以是列坐标的列表,代码实现如下:

import java.util.ArrayList;import java.util.HashMap;import java.util.Map;public class SetMatrixZeroes {    public static void setZeroes(int[][] matrix) {        if (matrix == null)            return;        if (matrix.length == 0)            return;        HashMap<Integer, ArrayList<Integer>> zeroElementsCoordinateSet = new HashMap<>();        for (int i = 0; i < matrix.length; i++) {            for (int j = 0; j < matrix[i].length; j++) {                if (matrix[i][j] == 0) {                    if (zeroElementsCoordinateSet.containsKey(i)) {                        ArrayList<Integer> arrayList = zeroElementsCoordinateSet.get(i);                        arrayList.add(j);                        zeroElementsCoordinateSet.put(i, arrayList);                    } else {                        ArrayList<Integer> arrayList = new ArrayList<>();                        arrayList.add(j);                        zeroElementsCoordinateSet.put(i, arrayList);                    }                }            }        }        for (Map.Entry<Integer, ArrayList<Integer>> entry : zeroElementsCoordinateSet.entrySet()) {            setMatrixRowZeros(matrix, entry.getKey());            for (Integer e : entry.getValue()) {                setMatrixColZeros(matrix, e);            }        }    }    private static void setMatrixRowZeros(int[][] matrix, int x) {        if (matrix == null)            return;        if (matrix.length == 0)            return;        if (matrix.length <= x)            return;        for (int i = 0; i < matrix[0].length; i++)            matrix[x][i] = 0;    }    private static void setMatrixColZeros(int[][] matrix, int y) {        if (matrix == null)            return;        if (matrix.length == 0)            return;        if (matrix[0].length <= y)            return;        for (int i = 0; i < matrix.length; i++)            matrix[i][y] = 0;    }    private static void printMatrix(int[][] matrix) {        if (matrix == null)            return;        if (matrix.length == 0) {            System.out.println("[]");            return;        }        System.out.println("[");        for (int[] aMatrix : matrix) {            System.out.print("  [");            for (int j = 0; j < aMatrix.length; j++) {                System.out.print(aMatrix[j]);                if (j != aMatrix.length - 1)                    System.out.print(", ");            }            System.out.println("]");        }        System.out.println("]");    }    public static void main(String[] args) {        int[][] matrix = new int[][]{{0, 0, 0, 5}, {4, 3, 1, 4}, {0, 1, 1, 4}, {1, 2, 1, 3}, {0, 0, 1, 1}};        setZeroes(matrix);        printMatrix(matrix);    }}

但是这么写貌似效率不是那么高,至少我们又使用了新空间HashMap,能不能再优化一下呢?

另一个想法就是争取在原地把这个事情搞定,我们可以观察到,如果某个坐标有为0的元素,那么这个坐标对应的第一行和第一列的元素也肯定为0,那么我们可以先处理一下坐标大于第一行和第一列的元素,这样做的目的就是为了将一个0转换为两个0,并且都放在了第一行和第一列,也就是做了边缘化的操作。

我们再观察,如果第一行或者第一列原本也有0元素的话,那么结果很显然,第一行和第一列要全部置0,如果在上一步的基础上,再特殊处理一下边界,那么这个问题就解决了,而且是原地解决:

public class SetMatrixZeroes {    public static void setZeroes(int[][] matrix) {        if (matrix == null)            return;        if (matrix.length  == 0)            return;        boolean firstRowHasZero = false;        boolean firstColHasZero = false;        for (int i = 0; i < matrix[0].length; i++) {            if (matrix[0][i] == 0) {                firstRowHasZero = true;            }        }        for (int i = 0; i < matrix.length; i++) {            if (matrix[i][0] == 0) {                firstColHasZero = true;            }        }        for (int i = 1; i < matrix.length; i++) {            for (int j = 1; j < matrix[i].length; j++) {                if (matrix[i][j] == 0) {                    matrix[i][0] = 0;                    matrix[0][j] = 0;                }            }        }        for (int i = 1; i < matrix[0].length; i++) {            if (matrix[0][i] == 0)                setMatrixColZeros(matrix, i);        }        for (int i = 1; i < matrix.length; i++) {            if (matrix[i][0] == 0)                setMatrixRowZeros(matrix, i);        }        if (firstRowHasZero) {            setMatrixRowZeros(matrix, 0);        }        if (firstColHasZero) {            setMatrixColZeros(matrix, 0);        }    }    private static void setMatrixRowZeros(int[][] matrix, int x) {        if (matrix == null)            return;        if (matrix.length == 0)            return;        if (matrix.length <= x)            return;        for (int i = 0; i < matrix[0].length; i++)            matrix[x][i] = 0;    }    private static void setMatrixColZeros(int[][] matrix, int y) {        if (matrix == null)            return;        if (matrix.length == 0)            return;        if (matrix[0].length <= y)            return;        for (int i = 0; i < matrix.length; i++)            matrix[i][y] = 0;    }    private static void printMatrix(int[][] matrix) {        if (matrix == null)            return;        if (matrix.length == 0) {            System.out.println("[]");            return;        }        System.out.println("[");        for (int[] aMatrix : matrix) {            System.out.print("  [");            for (int j = 0; j < aMatrix.length; j++) {                System.out.print(aMatrix[j]);                if (j != aMatrix.length - 1)                    System.out.print(", ");            }            System.out.println("]");        }        System.out.println("]");    }    public static void main(String[] args) {        int[][] matrix = new int[][]{{0, 0, 0, 5}, {4, 3, 1, 4}, {0, 1, 1, 4}, {1, 2, 1, 3}, {0, 0, 1, 1}};        setZeroesII(matrix);        printMatrix(matrix);    }}

这种方法的空间复杂度为O(1)。

原创粉丝点击