【字節專題】leetcode 221. 最大正方形

221. 最大正方形

在一個由 0 和 1 組成的二維矩陣內,找到只包含 1 的最大正方形,並返回其面積。

示例:
輸入: 
1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0

輸出: 4

不需要額外空間 直接原地dp

寫得有點醜,沒有大佬們的好看。

第一個for遍歷1~max_edge,也就是最長的邊。
第二三個for,判斷matrix[i][j]=='1' && matrix[i-1][j]=='1' && matrix[i][j-1]=='1' && matrix[i-1][j-1]=='1',也就是當前位置,以及它左上角的位置,以及左邊的位置,上邊的位置都爲1,說明可以組成邊長爲當前len的正方形。注意len爲1時只要找到一個就可以break了,len>1時,比如len==2,要遍歷所有可能的位置,更新matrix[i][j],這個是接下來len++後判斷需要使用的。最後可以做的剪枝,若在當前len下不能更新找到更大的正方形,則接下來更不可能找到了,直接break。
【注意】:這個matrix在不同的len下含義的不同的喔。

public static int maximalSquare(char[][] matrix) {
    if (matrix==null || matrix.length==0 || matrix[0]==null || matrix[0].length==0)    return 0;
    int row = matrix.length;
    int col = matrix[0].length;

    int max_edge = Math.min(row, col);
    int max_area = 0;
    for (int len = 1;len<=max_edge;len++){
        boolean flag = false;
        for (int i = row-1;i>=len-1;i--){
            for (int j = col-1;j>=len-1;j--){
                if (matrix[i][j]=='1' && len==1) {
                    max_area = Math.max(max_area, len * len);
                    flag = true;
                    break;
                }
                if (len!=1) {
                    if (matrix[i][j]=='1' && matrix[i-1][j]=='1' &&
                            matrix[i][j-1]=='1' && matrix[i-1][j-1]=='1'){
                        flag=true;
                        max_area = Math.max(max_area, len*len);
                    }else {
                        matrix[i][j]=0;
                    }
                }
            }
            if (flag && len==1)   break;
        }
        if (flag==false)
            break;
    }
    return max_area;
}

動態規劃

我們用一個例子來解釋這個方法:

0 1 1 1 0
1 1 1 1 1
0 1 1 1 1
0 1 1 1 1
0 0 1 1 1
  1. 我們用 0 初始化另一個矩陣 dp,維數和原始矩陣維數相同;
  2. dp(i,j) 表示的是由 1 組成的最大正方形的邊長;
  3. 從 (0,0) 開始,對原始矩陣中的每一個 1,我們將當前元素的值更新爲
    dp(i, j)=min(dp(i−1, j), dp(i−1, j−1), dp(i, j−1))+1
  4. 我們還用一個變量記錄當前出現的最大邊長,這樣遍歷一次,找到最大的正方形邊長 maxsqlen,那麼結果就是 maxsqlen^2。

可以通過下面的圖來理解該工作原理:
在這裏插入圖片描述

public class Solution {
    public int maximalSquare(char[][] matrix) {
        int rows = matrix.length, cols = rows > 0 ? matrix[0].length : 0;
        int[][] dp = new int[rows + 1][cols + 1];
        int maxsqlen = 0;
        for (int i = 1; i <= rows; i++) {
            for (int j = 1; j <= cols; j++) {
                if (matrix[i-1][j-1] == '1'){
                    dp[i][j] = Math.min(Math.min(dp[i][j - 1], dp[i - 1][j]), dp[i - 1][j - 1]) + 1;
                    maxsqlen = Math.max(maxsqlen, dp[i][j]);
                }
            }
        }
        return maxsqlen * maxsqlen;
    }
}

複雜度分析

  • 時間複雜度:O(mn)O(mn)。
  • 空間複雜度:O(mn)O(mn),用了一個大小相同的矩陣 dp。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章