1. 程式人生 > 實用技巧 >Leetcode 最大正方形(兩種解法)

Leetcode 最大正方形(兩種解法)

第一種解法:二維字首和暴力

維護一個二維的字首和f[i][j]表示從(1,1)到(i,j)的正方形矩陣的和。f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]

然後列舉每個點,並假設該點為右下角頂點,然後列舉正方形長度判斷滿不滿足條件即可,條件為:f[i][j]-f[i-k][j]-f[i][j-k]+f[i-k][j-k]==k*k

code:

class Solution {
public:
    int dp[1000][1000];
    int maximalSquare(vector<vector<char>>& matrix) { 
        
int n=matrix.size(); if(n==0) return 0; int m=matrix[0].size(); for(int i=1;i<=n;i++){ if(matrix[i-1][0]=='1'){ dp[i][1]+=1+dp[i-1][1]; } else dp[i][1]+=dp[i-1][1]; } for(int i=2;i<=m;i++){
if(matrix[0][i-1]=='1'){ dp[1][i]+=dp[1][i-1]+1; } else dp[1][i]+=dp[1][i-1]; } for(int i=2;i<=n;i++){ for(int j=2;j<=m;j++){ dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]; if(matrix[i-1][j-1]=='1'
) dp[i][j]+=1; } } int ans=0; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(matrix[i-1][j-1]=='0') continue ; int c=min(i,j); for(int k=1;k<=c;k++){ if(dp[i][j]-dp[i-k][j]-dp[i][j-k]+dp[i-k][j-k]==k*k) ans=max(ans,k*k); else break; } } } return ans; } };

第二種解法:dp

定義dp[i][j]表示以(i,j)為右下角點所能構成的正方形的最大邊長。

dp[i][j]=min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])+1

方程證明:

假如說我們dp[i][j]由dp[i-1][j]即i,j上邊的點轉移過來,因為他是正方形,所以高度和寬度應該同時加一。新正方形以(i,j)為右下角的邊長為dp[i-1][j]+1,也就是說從 (i,j)到點(i-dp[i-1][j],j)都應該是1,我們再來看看(i,j-1)這個點,他的正方形邊長為dp[i][j-1]。即從(i-1,j)到(i-dp[i][j-1],j-1)都應該是1.所以應該滿足i-dp[i][j-1]<=i-dp[i-1][j];即dp[i-1][j]<=dp[i][j-1]。同理可得dp[i-1][j]<=dp[i-1][j-1]即我們選擇的總是三個裡邊最小的。

code:

class Solution {
public:
    int dp[1000][1000];
    int maximalSquare(vector<vector<char>>& matrix) {
        int n=matrix.size();
        if(n==0) return 0;
        int m=matrix[0].size();
        int ans=0;
        for(int i=1;i<=n;i++){
            if(matrix[i-1][0]=='1'){
                 dp[i][1]=1;
                 ans=1;
            }
        }
        for(int j=1;j<=m;j++){
            if(matrix[0][j-1]=='1') {
                dp[1][j]=1;
                ans=1;
            }
        }
        for(int i=2;i<=n;i++){
            for(int j=2;j<=m;j++){
                if(matrix[i-1][j-1]=='1') {
                    dp[i][j]=min(dp[i-1][j],min(dp[i][j-1],dp[i-1][j-1]))+1;
                    ans=max(ans,dp[i][j]);
                }
            }
        }
        return ans*ans;
    }
};