题目链接

链接:https://leetcode.com/problems/max-sum-of-rectangle-no-larger-than-k/description/

题解&代码

1、暴力枚举所有的情况,时间复杂度O(n2*m2),实际耗时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(m2*n2),实际耗时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的更多相关文章

  1. 363. Max Sum of Rectangle No Larger Than K

    /* * 363. Max Sum of Rectangle No Larger Than K * 2016-7-15 by Mingyang */ public int maxSumSubmatri ...

  2. [LeetCode] 363. Max Sum of Rectangle No Larger Than K 最大矩阵和不超过K

    Given a non-empty 2D matrix matrix and an integer k, find the max sum of a rectangle in the matrix s ...

  3. 【LeetCode】363. Max Sum of Rectangle No Larger Than K 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址: https://leetcode.com/problems/max-sum- ...

  4. 【leetcode】363. Max Sum of Rectangle No Larger Than K

    题目描述: Given a non-empty 2D matrix matrix and an integer k, find the max sum of a rectangle in the ma ...

  5. [LeetCode] Max Sum of Rectangle No Larger Than K 最大矩阵和不超过K

    Given a non-empty 2D matrix matrix and an integer k, find the max sum of a rectangle in the matrix s ...

  6. Leetcode: Max Sum of Rectangle No Larger Than K

    Given a non-empty 2D matrix matrix and an integer k, find the max sum of a rectangle in the matrix s ...

  7. 363 Max Sum of Rectangle No Larger Than K 最大矩阵和不超过K

    Given a non-empty 2D matrix matrix and an integer k, find the max sum of a rectangle in the matrix s ...

  8. [Swift]LeetCode363. 矩形区域不超过 K 的最大数值和 | Max Sum of Rectangle No Larger Than K

    Given a non-empty 2D matrix matrix and an integer k, find the max sum of a rectangle in the matrix s ...

  9. Max Sum of Rectangle No Larger Than K

    Given a non-empty 2D matrix matrix and an integer k, find the max sum of a rectangle in the matrix s ...

随机推荐

  1. mvc、mvp和mvvm理解

    MVC.MVP.MVVM这些模式是为了解决开发过程中的实际问题而提出来的,目前作为主流的几种架构模式而被广泛使用. 一.MVC(Model-View-Controller) MVC是比较直观的架构模式 ...

  2. 用requests爬取一个招聘网站

    import requestsimport re session = requests.session()第一步:访问登陆页,拿到X_Anti_Forge_Token,X_Anti_Forge_Cod ...

  3. D - C Looooops POJ - 2115 欧几里德拓展

    题意:就是看看for(; ;)多久停止. 最让我蛋疼的是1L和1LL的区别!让我足足wa了12发! 1L 是long类型的, 1LL为long long类型的! 思路: 这就是欧几里德扩展的标准式子了 ...

  4. Javascript中的undefined、null、""、0值和false的区别总结

    在程序语言中定义的各种各样的数据类型中,我们都会为其定义一个"空值"或"假值",比如对象类型的空值null,.NET Framework中数据库字段的空值DBN ...

  5. metamask源码学习-background.js

    这个就是浏览器后台所进行操作的地方了,它就是页面也区块链进行交互的中间部分. metamask-background描述了为web扩展单例的文件app/scripts/background.js.该上 ...

  6. linux如何查看端口被哪个进程占用

    1.lsof -i:端口号 2.netstat -tunlp|grep 端口号 都可以查看指定端口被哪个进程占用的情况 工具/原料   linux,windows xshell 方法/步骤     [ ...

  7. MATLAB中floor、round、ceil、fix区别

    Matlab取整函数有: fix, floor, ceil, round.具体应用方法如下:fix朝零方向取整,如fix(-1.3)=-1; fix(1.3)=1;floor,顾名思义,就是地板,所以 ...

  8. MATLAB:控制系统模型变换

    1.多项式转换为零极点 [z,p,k]=tf2zp(num,den); 2.零极点转换为多项式 [num,den]=zp2tf(z,p,k); 3.状态空间转换成多项式传递函数 [num,den]=s ...

  9. FreeRTOS队列

    简单来讲队列是任务间通信的方式,队列本身是可以存储消息的,队列的消息可以由一个或者多个任务写入,也可以由一个或者多个任务读出,总之消息队列是任务间通信方式:

  10. jsp中使用原生js实现异步交互

    Ajax的工作原理相当于在用户和服务器之间加了—个中间层,使用户操作与服务器响应异步化.并不是所有的用户请求都提交给服务器,像—些数据验证和数据处理等都交给Ajax引擎自己来做,只有确定需要从服务器读 ...