Leetcode363

思路: 一种naive的算法就是枚举每个矩形块, 时间复杂度为O((mn)^2), 可以做少许优化时间复杂度可以降低到O(mnnlogm), 其中m为行数, n为列数. 

先求出任意两列之间的所有数的和, 然后再枚举任意两行之间的和, 而我们优化的地方就在后者. 我们用s[x]来表示第x行从a列到b列的和. 遍历一遍从第0行到最后一行的求和数组, 并依次将其放到二叉搜索树中, 这样当我们知道了从第0行到当前行的和的值之后, 我们就可以用lower_bound在O(log n)的时间复杂度内找到能够使得从之前某行到当前行的矩阵值最接近k. 也就是说求在之前的求和数组中找到第一个位置使得大于(curSum - k), 这种做法的原理是在curSum之下规定了一个bottom-line, 在这上面的第一个和就是(curSum-val)差值与k最接近的数. 还需要注意的是预先为二叉搜索树加一个0值, 这种做法的原理是如果当前curSum小于k, 那么至少本身是一个潜在的解. 说的有点乱, 请见谅, 不懂的请提问!

class Solution {  
public:  
    int maxSumSubmatrix(vector<vector<int>>& matrix, int k) {  
        if(matrix.size()==0) return 0;  
        int row = matrix.size(), col = matrix[0].size();  
        int ans =INT_MIN;  
        for(int i = 0; i < col; i++)  
        {  
            vector<int> sum(row, 0);  
            for(int j =i; j < col; j++)  
            {  
                set<int> st{0};  
                int curSum =0, curMax = INT_MIN;  
                for(int x = 0; x < row; x++)  
                {  
                    sum[x] += matrix[x][j];  
                    curSum += sum[x];  
                    auto it = st.lower_bound(curSum-k);  
                    if(it!=st.end()) curMax = max(curSum - *it, curMax);  
                    st.insert(curSum);  
                }  
                ans = max(curMax, ans);  
            }  
        }  
        return ans;  
    }  
};  

  

posted on 2017-05-18 20:24  Bingsen  阅读(202)  评论(0编辑  收藏  举报