363. Max Sum of Rectangle No Larger Than K (Hard)

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:

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

Solution 1: Brute Force + DP 1658 ms

Time Complexity: $$O(n^4)$$

这道题给了我们一个二维数组,让我们求和不超过的K的最大子矩形,那么我们首先可以考虑使用brute force来解,就是遍历所有的子矩形,然后计算其和跟K比较,找出不超过K的最大值即可。就算是暴力搜索,我们也可以使用优化的算法,比如建立累加和,参见之前那道题Range Sum Query 2D - Immutable,我们可以快速求出任何一个区间和,那么下面的方法就是这样的,当遍历到(i, j)时,我们计算sum(i, j),表示矩形(0, 0)到(i, j)的和,然后我们遍历这个矩形中所有的子矩形,计算其和跟K相比,这样既可遍历到原矩形的所有子矩形,参见代码如下:

class Solution {
public:
    int maxSumSubmatrix(vector<vector<int>>& matrix, int k) {
        if (matrix.empty() || matrix[0].empty()) return 0;
        int n = matrix.size(), m = matrix[0].size(), res = INT_MIN;
        int dp[n][m];
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
                int t = matrix[i][j];
                if (i > 0) t += dp[i-1][j];
                if (j > 0) t += dp[i][j-1];
                if (i > 0 && j > 0) t -= dp[i-1][j-1];
                dp[i][j] = t;
                for (int r = 0; r <= i; ++r) {
                    for (int c = 0; c <= j; ++c) {
                        int d = dp[i][j];
                        if (r > 0) d -= dp[r-1][j];
                        if (c > 0) d -= dp[i][c-1];
                        if (r > 0 && c > 0) d += dp[r-1][c-1];
                        if (d <= k) res = max(res, d);
                    }
                }
            }
        }
        return res;
    }
};

Solution 2: Kadane's Algorithm 975ms

Time Complexity: $$O(n^3*logn)$$

int maxSumSubmatrix(vector<vector<int>>& matrix, int k) {
    if (matrix.empty()) return 0;
    int row = matrix.size(), col = matrix[0].size(), res = INT_MIN;

    for (int l = 0; l < col; ++l) {
        vector<int> sums(row,0);
        for (int r = l; r < col; ++r) {
            int cum = 0;
            set<int> cumset;
            cumset.insert(0);
            for (int i = 0; i < row; ++i) {
                sums[i] += matrix[i][r];
                // Find the max subarray no more than K
                cum += sums[i];
                // cum(i, j]: cum[j]-cum[i] <= k
                // cum-k: cum[i] >= cum[j]-k
                auto it = cumset.lower_bound(cum-k);
                if (it != cumset.end()) {
                    if (res < cum-*it) res = cum-*it;
                    if (res == k) return k;
                }
                cumset.insert(cum);
            }
        }
    }
    return res;
}

improved version: 49ms

class Solution {
    int maxSumArray(vector<int>& arr, int k) {
        int sum = 0, res = INT_MIN;
        // first, compute maxSumArray
        for (int i = 0; i < arr.size(); ++i) { //it's a trick. Maybe O(n) to solve this problem
            sum += arr[i];
            res = max(sum, res);
            if (sum == k) return sum;
            if (sum < 0) sum = 0;
        }
        if (res <= k) return res;

        // maxSumArrayNoLargerThank
        res = INT_MIN;
        sum = 0;
        set<int> cumset; cumset.insert(0);
        for (int i = 0; i < arr.size(); ++i) {
            sum += arr[i];
            auto it = cumset.lower_bound(sum-k);
            if (it != cumset.end()) res = max(res, sum-*it);
            cumset.insert(sum);
        }

        return res;
    }

public:
    int maxSumSubmatrix(vector<vector<int>>& matrix, int k) {
        if (matrix.size() == 0) return 0;
        int m = matrix.size(), n = matrix[0].size(), res = INT_MIN;

        for (int l = 0; l < n; ++l) {
            vector<int> sum(m, 0);
            for (int r = l; r < n; ++r) {
                for (int i = 0; i < m; ++i) {
                    sum[i] += matrix[i][r];
                }
                int ms = maxSumArray(sum, k);
                if (ms == k) return ms;
                if (ms < k && ms > res) res = ms;
            }
        }

        return res;
    }
};

Solution 3: Merge Sort

心情不太好

results matching ""

    No results matching ""