LeetCode 363:Max Sum of Rectangle No Larger Than K
2017-08-03 11:50
531 查看
题目链接
题解&代码
1、暴力枚举所有的情况,时间复杂度O(n^2*m^2),实际耗时759 ms
class Solution { public: int maxSumSubmatrix(vector<vector<int> >& matrix, int k) { int n=matrix.size(),m=matrix[0].size(); vector<vector<int> > sumv(n+1,vector<int>(m+1,0)); for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { sumv[i][j]=matrix[i-1][j-1]+sumv[i-1][j]+sumv[i][j-1]-sumv[i-1][j-1]; } } int ans=-INF; for(int i1=1;i1<=n;i1++){ for(int j1=1;j1<=m;j1++){ for(int i2=i1;i2<=n;i2++){ for(int j2=j1;j2<=m;j2++){ int val=sumv[i2][j2]-sumv[i1-1][j2]-sumv[i2][j1-1]+sumv[i1-1][j1-1]; if(val<=k){ ans=max(ans,val); } } } } } return ans; } private: static const int INF=0x3f3f3f3f; };
2、先通过枚举一维进行降维,然后再暴力枚举所有区间,时间复杂度O(m^2*n^2),实际耗时736ms。
class Solution { public: int maxSumSubmatrix(vector<vector<int> >& matrix, int k) { int n=matrix.size(),m=matrix[0].size(); vector<vector<int> > sumv(n+1,vector<int>(m+1,0)); for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { sumv[i][j]=sumv[i][j-1]+matrix[i-1][j-1]; } } int ans=-INF; vector<int> arr(n+1); for(int len=1; len<=m; len++) { for(int j=len; j<=m; j++) { arr[0]=0; for(int i=1; i<=n; i++) { int val=sumv[i][j]-sumv[i][j-len]; arr[i]=val+arr[i-1]; } for(int i=1;i<=n;i++){ for(int j=0;j<i;j++){ int x=arr[i]-arr[j]; if(x<=k) ans=max(ans,x); } } } } return ans; } private: static const int INF=0x3f3f3f3f; };
3、 第2种方法基础上加一个剪枝,在枚举区间之前,先用dp(O(n))求出最大值区间和最小值区间,然后判断k是否在区间内,时间复杂度:‘玄学’,实际耗时19ms。
class Solution { public: int maxSumSubmatrix(vector<vector<int> >& matrix, int k) { int n=matrix.size(),m=matrix[0].size(); vector<vector<int> > sumv(n+1,vector<int>(m+1,0)); for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { sumv[i][j]=sumv[i][j-1]+matrix[i-1][j-1]; } } int ans=-inf; vector<int> arr(n+1); for(int len=1; len<=m; len++) { for(int j=len; j<=m; j++) { arr[0]=0; LL mi=inf,ma=-inf; LL pre=inf,aft=-inf; for(int i=1; i<=n; i++) { int val=sumv[i][j]-sumv[i][j-len]; arr[i]=val+arr[i-1]; pre=min(pre+val,(LL)val); aft=max(aft+val,(LL)val); mi=min(mi,pre); ma=max(ma,aft); } if(k<mi) continue; else if(k==mi) { ans=k; } else if(k>=ma) { ans=max((LL)ans,ma); } else { for(int i=1; i<=n; i++) { for(int j=0; j<i; j++) { int x=arr[i]-arr[j]; if(x<=k) ans=max(ans,x); } } if(ans==k) return ans; } } } return ans; } private: static const int inf=0x7fffffff; typedef long long LL; };
4、正解:先降维,然后枚举区间终点,用set维护前缀和,用lower_bound去查区间起点,从而O(nlogn)的复杂度解决该问题的一维版本。加上降维的时间复杂度为O(m^2*nlogn)。实际耗时:259ms。
class Solution { public: int maxSumSubmatrix(vector<vector<int> >& matrix, int k) { int n=matrix.size(),m=matrix[0].size(); vector<vector<int> > sumv(n+1,vector<int>(m+1,0)); for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { sumv[i][j]=sumv[i][j-1]+matrix[i-1][j-1]; } } int ans=-INF; vector<int> pre(n+1),arr(n+1); set<pair<int,int> > myset; set<pair<int,int> >::iterator it; for(int len=1; len<=m; len++) { for(int j=len; j<=m; j++) { pre[0]=0; myset.clear(); for(int i=1; i<=n; i++) { arr[i]=sumv[i][j]-sumv[i][j-len]; pre[i]=arr[i]+pre[i-1]; myset.insert(make_pair(pre[i],i)); } for(int i=1;i<=n;i++){ if(arr[i]<=k) ans=max(ans,arr[i]); int key=k-arr[i]+pre[i]; it=myset.lower_bound(make_pair(key,0x7fffffff)); if(it!=myset.begin()){ it--; int tmp=it->first; ans=max(ans,tmp-pre[i]+arr[i]); } myset.erase(make_pair(pre[i],i)); } } } return ans; } private: static const int INF=0x7fffffff; };
5、正解优化版本(空间优化+常数优化)实际耗时:162ms。
class Solution { public: int maxSumSubmatrix(vector<vector<int> >& matrix, int k) { int n=matrix.size(),m=matrix[0].size(); int mi=min(n,m),ma=max(n,m); bool isColMax=m>n; int ans=-2147483648; for(int st=1; st<=mi; st++) { vector<int> arr(ma+1,0); for(int ed=st; ed<=mi; ed++) { set<int> myset; int cnt=0; myset.insert(cnt); for(int i=1; i<=ma; i++) { arr[i]+=isColMax?matrix[ed-1][i-1]:matrix[i-1][ed-1]; cnt+=arr[i]; set<int>::iterator it=myset.lower_bound(cnt-k); if(it!=myset.end()) ans=max(ans,cnt-*it); myset.insert(cnt); } } } return ans; } };
6、方法5+方法3提到的dp剪枝:实际耗时:19ms。
class Solution { public: int maxSumSubmatrix(vector<vector<int> >& matrix, int k) { int n=matrix.size(),m=matrix[0].size(); int mi=min(n,m),ma=max(n,m); bool isColMax=m>n; int ans=-2147483648; for(int st=1; st<=mi; st++) { vector<int> arr(ma+1,0); for(int ed=st; ed<=mi; ed++) { set<int> myset; int cnt=0; myset.insert(cnt); for(int i=1; i<=ma; i++) { arr[i]+=isColMax?matrix[ed-1][i-1]:matrix[i-1][ed-1]; cnt+=arr[i]; set<int>::iterator it=myset.lower_bound(cnt-k); if(it!=myset.end()) ans=max(ans,cnt-*it); myset.insert(cnt); } } } return ans; } };
相关文章推荐
- [leetcode-363]Max Sum of Rectangle No Larger Than K(java)
- LeetCode 363 Max Sum of Rectangle No Larger Than K (二分)
- leetcode(363):Max Sum of Rectangle No Larger Than K
- Leetcode Max Sum of Rectangle No Larger Than K
- LeetCode-Max Sum of Rectangle No Larger Than K
- [LeetCode] Max Sum of Rectangle No Larger Than K
- leetCode_Max Sum of Rectangle No Larger Than K
- Leetcode: Max Sum of Rectangle No Larger Than K
- 【Leetcode】Max Sum of Rectangle No Larger Than K
- [LeetCode] Max Sum of Rectangle No Larger Than K 最大矩阵和不超过K
- [LeetCode]Max Sum of Rectangle No Larger Than K
- Max Sum of Rectangle No Larger Than K
- Max Sum of Rectangle No Larger Than K
- [TODO] LeetCode #363: Max Sum of Rectangle No Larger Than K
- Max Sum of Rectangle No Larger Than K
- Max Sum of Rectangle No Larger Than K
- Max Sum of Rectangle No Larger Than K
- Max Sum of Rectangle No Larger Than K
- max-sum-of-sub-matrix-no-larger-than-k
- 【Leetcode】363. Max Sum of Rectangle No Larger Than K