码迷,mamicode.com
首页 > 其他好文 > 详细

363. Max Sum of Rectangle No Larger Than K

时间:2021-04-23 12:08:39      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:时间   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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!