1. 程式人生 > >LeetCode筆記——73矩陣置零

LeetCode筆記——73矩陣置零

題目:

給定一個 m x n 的矩陣,如果一個元素為 0,則將其所在行和列的所有元素都設為 0。請使用原地演算法

示例 1:

輸入: 
[
  [1,1,1],
  [1,0,1],
  [1,1,1]
]
輸出: 
[
  [1,0,1],
  [0,0,0],
  [1,0,1]
]

示例 2:

輸入: 
[
  [0,1,2,0],
  [3,4,5,2],
  [1,3,1,5]
]
輸出: 
[
  [0,0,0,0],
  [0,4,5,0],
  [0,3,1,0]
]

進階:

  • 一個直接的解決方案是使用  O(mn) 的額外空間,但這並不是一個好的解決方案。
  • 一個簡單的改進方案是使用 O(m + n) 的額外空間,但這仍然不是最好的解決方案。
  • 你能想出一個常數空間的解決方案嗎?

思路:我自己寫的程式碼不對,然後就在網上找了大神的程式碼。原文連結:https://blog.csdn.net/derrantcm/article/details/47371979。大神程式碼的執行速度是最快的,但是和leetcode中最快的程式碼好像有點不一樣。

這個題目中要求在原地完成,並且希望在常數空間內完成,這個要求我有點不太懂。以下程式碼的基本思想是首先對陣列中的0元素進行標記。以第一行和第一列作為一個標誌位,若某個元素為0,那麼在它對應的第一行和第一列的位置上都設定為0;同時為了區分這個0元素是否為與第一行和第一列上,還設定了兩個標誌位。在標記完成陣列之後,分兩部分進行置零操作,一部分是第一行和第一列中的元素,這些元素是否全部置零是根據之前的兩個標誌位來判斷;第二部分是剩餘部分,它們是否置零是由對應的第一行或者第一列中是否為零來判斷。這種思路應該就是使用了常數空間,只使用了額外的兩個標誌位。

程式碼:

public class Solution {
    public void setZeroes(int[][] matrix) {
        // 第一行被設定的標誌 這個標誌位標記的是0元素是否在第一行
        boolean rowFlag = false;
        // 第一列被設定的標誌 標記這個0元素是否在第一列
        boolean colFlag = false;
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
                if (matrix[i][j] == 0) {
                    // 標記第一行要被設定
                    if (i == 0)
                    {
                        rowFlag = true;
                    }
                    // 標記第一列要被設定
                    if (j == 0){
                        colFlag = true;
                    }
                    // 在行列在標記要設定為0的行和列
                    matrix[0][j] = 0;
                    matrix[i][0] = 0;
                }
            }
        }
        // 對第二行第二列開始的元素設定0
        for (int i = 1; i < matrix.length; i++) {
            for (int j = 1; j < matrix[0].length; j++) {
                if (matrix[i][0] == 0 || matrix[0][j] == 0) {
                    matrix[i][j] = 0;
                }
            }
        }
        // 設定第一行為0
        if (rowFlag) {
        for (int j = 0; j < matrix[0].length; j++) {
            matrix[0][j] = 0;
        }
        }
        // 設定第一列為0
        if (colFlag) {
            for (int i = 0; i < matrix.length; i++) {
                matrix[i][0] = 0;
            }
        }
    }
}


自己寫的程式碼 

我還不知道是哪裡錯了。。。。。。。應該不是使用常數的空間,並且好像引數的傳遞也有點問題吧

class Solution {
    public void setZeroes(int[][] matrix) {
      int m=matrix.length;
      int n=matrix[0].length;
    for(int i=0;i<m;i++){
        for(int j=0;j<n;j++){
            if(matrix[i][j]==0)
                ss(matrix,i,j);
            continue;
        }
    }
    }

    private void ss(int[][]a,int b,intc){  //總是提示這一行不正確
    for(int i=0;i<n;i++){
        a[b][i]==0;
    }
    for(int j=0;j<m;j++){
        a[j][c]==0;
    }
}
    
}

 

以下是leetcode中執行最快的程式碼:

基本思想和上面的分析一致,只不過只使用另一個標誌位。

class Solution {
    public void setZeroes(int[][] matrix) {
        int col0 = 1;
        int m = matrix.length;
        int n = matrix[0].length;
        for(int i = 0; i < m; i++){
            if(matrix[i][0] == 0)
                col0 = 0;
            for(int j = 1; j < n; j++)
                if(matrix[i][j] == 0)
                    matrix[0][j] = matrix[i][0] = 0;
        }
        for(int i = m-1; i >= 0; i--){
            for(int j = n-1; j >= 1; j--)
                if( matrix[0][j] == 0 || matrix[i][0] == 0)
                    matrix[i][j] = 0;
            if(col0 == 0)
                matrix[i][0] = 0;
        }
    }
}