Leetcode 最大正方形(兩種解法)
阿新 • • 發佈:2020-09-08
第一種解法:二維字首和暴力
維護一個二維的字首和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; } };