https://leetcode-cn.com/problems/max-sum-of-rectangle-no-larger-than-k/
思路:暴力枚举的话是
O
(
n
2
m
2
)
O(n^2m^2)
O(n2m2)的,肯定过不了。考虑枚举左右边界
l
、
r
l、r
l、r,然后计算
a
[
i
]
=
∑
j
=
l
r
m
a
t
r
i
x
[
i
]
[
j
]
a[i]=\sum_{j=l}^{r}matrix[i][j]
a[i]=∑j=lrmatrix[i][j],那么问题就转换为:在长度为
n
n
n的数组
a
a
a中,找到一个区间
s
、
t
s、t
s、t,使得
a
s
+
…
+
a
t
a_s+…+a_t
as+…+at最大且这个最大值
<
=
k
<=k
<=k。我们可以从前向后遍历数组
a
a
a并记录前缀和
s
u
m
sum
sum,那么对于任意
s
u
m
t
sum_t
sumt,符合题意的
s
u
m
s
sum_s
sums满足
s
u
m
t
−
s
u
m
s
<
=
k
sum_t-sum_s<=k
sumt−sums<=k,也即
s
u
m
s
>
=
s
u
m
t
−
k
sum_s>=sum_t-k
sums>=sumt−k,所以我们只需要找到
>
=
s
u
m
t
−
k
>=sum_t-k
>=sumt−k的最小的数,用
s
e
t
set
set维护即可。总体复杂度
O
(
m
2
n
l
g
n
)
O(m^2nlgn)
O(m2nlgn)。
注:我的 n 、 m n、m n、m和题目中的 n 、 m n、m n、m是相反的。
class Solution {
public:
int maxSumSubmatrix(vector<vector<int>>& matrix, int k) {
int n=matrix.size(),m=matrix[0].size();
vector<vector<int>> sum(n+1,vector<int>(m+1));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
sum[i][j]=sum[i][j-1]+matrix[i-1][j-1];
int ans=-0x3f3f3f3f;
for(int i=1;i<=m;i++)
{
for(int j=i;j<=m;j++)
{
//[i,j]列
set<int> s{0};
int base=0;
for(int t=1;t<=n;t++)
{
base+=sum[t][j]-sum[t][i-1];
auto it=s.lower_bound(base-k);
if(it!=s.end())
ans=max(ans,base-*it);
s.insert(base);
}
}
}
return ans;
}
};