标签:时间 cto 二分查找 排序 时间复杂度 vector i++ 最大 lower
思路:
通过把二维矩阵转化为一维来求解,我们的一维并不是对矩阵处理,一维数组是一列的元素和。
首先我们定义上边界,上边界从第一行开始,然后创建一个数组,每一个上边界创建一次数组,然后再定义一个下边界,从上边界的位置开始。然后求解上下边界组成的矩阵中第0列到最后一列的每一列和。
因为矩阵还需要有左右边界,这左右边界就是确定上下边界后要商讨的。
我们令左边界为Sl,右边界为Sr,我们将sum作为第0列到该列的和,那么 对于矩阵左右边界为Sl和Sr的矩阵,有sum[Sr]-sum[Sl]为子矩阵的和,我们要求其不大于k,就有sum[Sr]-sum[Sl]<=k,变换得到sum[Sr]-k<=sum[Sl]。所以我们需要找到第一个大于等于sum[Sr]-k的和。那么为了减少时间复杂度,我们使用二分查找。
代码:
class Solution {
public:
int maxSumSubmatrix(vector<vector<int>>& matrix, int k) {
int res =INT_MIN;
int r=matrix.size(),c=matrix[0].size();
for(int i=0;i<r;i++){ //定位上边界
vector<int> sum(c);
for(int j=i;j<r;++j){ //定位下边界
for(int n=0;n<c;++n){
sum[n] +=matrix[j][n]; //更新上下边界组成的子矩阵的每列的元素和,这样就能将求子矩阵和问题换成一维数组进行处理
}
set<int> sumset{0}; // set自动排序,是为了方便进行二分查找 找到第一个大于等于s-k的元素的位置
int s=0;
for(int v:sum){
s+=v; //等效为扩展右边界,每 加一个v,右边界就右移,虽然此时左边界还为第0列,后面lower_bound就是二分查找满足条件的左边界
auto lb =sumset.lower_bound(s-k);//这里是s-k的原因是 对于左右边界为Sl和Sr的子矩阵,应该有sum[Sr]-sum[Sl]<=k,所以有sum[Sr]-k<=sum[Sl]。这里s为sum[Sr]是因为s是从第一列累加的。因为是对v-0的列这个范围找Sl所以 Sl都在v左边。
if(lb != sumset.end()){ //只要有满足的Sl存在就能取Sr-Sl的最大和
res = max(res,s-*lb);
} //如果没有这个不小于s-k的元素,那么这个和就不满足小于等于k的要求,那么就不用取最大值,跳过即可
sumset.insert(s);
}
}
}
return res;
}
};
363. Max Sum of Rectangle No Larger Than K
标签:时间 cto 二分查找 排序 时间复杂度 vector i++ 最大 lower
原文地址:https://www.cnblogs.com/Mrsdwang/p/14691175.html