LeetCode [363. Max Sum of Rectangle No Larger Than K] 难度[hard]

来源:互联网 发布:http 前端展示数据库 编辑:程序博客网 时间:2024/06/06 01:52

题目

Given a non-empty 2D matrix matrix and an integer k, find the max sum of a rectangle in the matrix such that its sum is no larger than k.

Example:
Given matrix = [
[1, 0, 1],
[0, -2, 3]
]
k = 2
The answer is 2. Because the sum of rectangle [[0, 1], [-2, 3]] is 2 and 2 is the max number no larger than k (k = 2).

Note:
The rectangle inside the matrix must have an area > 0.
What if the number of rows is much larger than the number of columns?

解题思路:

最先想到的是暴力解法,把所有可能的矩阵都算一遍然后找出比k小的最大的,这样时间复杂度是O(n4),效率是很低的,因为有许多重复计算,要优化算法就要减少重复计算。可以一列列推过去,用一个sum记录每一行的起始列到当前列之和,然后再把每行遍历一遍,从而减少重复计算次数。这样遍历的矩阵的左上角都是在第一行,中间的矩阵的和可以通过相减获得,第i行到第j行的和 = 第j行的和 - 第i行的和。
又由于题目有限制矩阵之和要小于k,所以可以使用一个集合,把每一行之和都放进去,然后每得到新的和s,都在集合里用lower_bound函数找出在s-k右边的最小的数,然后用s减去这个数,就是当前行可以找的一个小于k的矩阵和,这里还有一个小细节就是要把0放进集合里面,这样就可以使得当s刚好为k的时候,可以返回k。该算法的算法时间复杂度为O(n3logn),这样说可能不太清楚,具体请看如下代码:(可AC)

class Solution {public:    int maxSumSubmatrix(vector<vector<int>>& matrix, int k) {        int row = matrix.size(), col = matrix[0].size();        int res = INT_MIN;        for(int i=0; i<col; ++i){   //第i列开始            vector<int> sum(row,0);            for(int j=i; j<col; ++j){   //第j列结束                for(int h=0; h<row; ++h)                    sum[h] += matrix[h][j]; //每一行累加的和,减少重复计算                set<int> sums;                 int s=0,maxS=INT_MIN;                sums.insert(0);                for(int h=0; h<row; ++h){                    s += sum[h];                    //获取插入s而不破坏set顺序的最小位置的指针                    set<int>::iterator it = sums.lower_bound(s-k);                    if(it!=sums.end())  maxS = max(s-*it,maxS);                    if(maxS == k)   return k;                    sums.insert(s);                }                res = max(res,maxS);            }        }        return res;    }};

额外思考:
如果题目没有要求矩阵和小于k,而是只要求最大的,则可以有O(n3)的算法,代码如下(没有k限制版)

int maxSumSubmatrix(vector<vector<int>>& matrix, int k) {        int row = matrix.size(), col = matrix[0].size();        int res = INT_MIN;        for(int i=0; i<col; ++i){   //第i列开始            vector<int> sum(row,0);            for(int j=i; j<col; ++j){   //第j列结束                for(int h=0; h<row; ++h)                    sum[h] += matrix[h][j]; //每一行累加的和,减少重复计算               int s = 0;                for(int h=0; h<row;++h){                    s += sum[h];                    if(s==k)    return k;                    if(s>res && s<k)   res = s;                    if(s<0) s = 0;                }            }        }        return res;    }
0 0
原创粉丝点击