您的位置:首页 > 其它

[LeetCode] Maximal Square(!!!!DP优化)

2015-08-27 20:13 148 查看
定义一个D[i][j] 表示的是以i,j为右下角的最大子正方形的边长。这个边长是受限于D[i-1][j],D[i][j-1] ,D[i-1][j-1]中最小的那个的。

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

}
};


12ms AC

这里的方法需要两次初始化,代码可以被进一步优化。因为每次D[i][j]的求解 只依赖于D[i-1][j],D[i][j-1] ,D[i-1][j-1],所以实际上可以只维护两个行向量或列向量,这样空间复杂度变成了O(2m)或O(2n)

class Solution {
public:
int maximalSquare(vector<vector<char>>& A) {
int m = A.size();   if(m==0)    return 0;
int n = A[0].size();    if(n==0)    return 0;
vector<int> pre(n,0);
vector<int> curr(n,0);
int max_area=0;
for(int i=0; i<n; ++i){
pre[i]=A[0][i]-'0';
if(A[0][i]=='1')
max_area = 1;
}
for(int i =1; i<m; ++i){
curr[0]=A[i][0]-'0';
for(int j = 1; j<n; ++j)
if(A[i][j]=='1'){
curr[j]= min(min(pre[j-1],pre[j]),curr[j-1])+1;
max_area = max(max_area, curr[j]);
}
//swap(pre,curr);
//curr=vector<int>(n,0);
pre.swap(curr);
fill(curr.begin(),curr.end(),0);

}
return max_area*max_area;

}
};


上面的swap(两种swap都是可以的)操作查了下是常数级的时间复杂度,它不涉及到元素的复制、移动、交换操作。这样的方式和使用指针的效果是相同的。

其实进一步优化可以将空间复杂度降低到O(m)

int maximalSquare(vector<vector<char>>& matrix) {
if (matrix.empty()) return 0;
int m = matrix.size(), n = matrix[0].size();
vector<int> dp(m + 1, 0);
int maxsize = 0, pre = 0;
for (int j = 0; j < n; j++) {
for (int i = 1; i <= m; i++) {
int temp = dp[i];
if (matrix[i - 1][j] == '1') {
dp[i] = min(dp[i], min(dp[i - 1], pre)) + 1;
maxsize = max(maxsize, dp[i]);
}
else dp[i] = 0;
pre = temp;
}
}
return maxsize * maxsize;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: