|
| 1 | +// 363. Max Sum of Rectangle No Larger Than K |
| 2 | + |
| 3 | +// 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. |
| 4 | + |
| 5 | +// Example: |
| 6 | +// Given matrix = [ |
| 7 | +// [1, 0, 1], |
| 8 | +// [0, -2, 3] |
| 9 | +// ] |
| 10 | +// k = 2 |
| 11 | +// 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). |
| 12 | + |
| 13 | +// Note: |
| 14 | +// The rectangle inside the matrix must have an area > 0. |
| 15 | +// What if the number of rows is much larger than the number of columns? |
| 16 | + |
| 17 | +// TLE还要就是最开始一直数组越界,直到把left right初始化为matrix,以及要最开始判定left, right关系,不能光依靠row1,row2,因为负数的取余操作是不定的。 |
| 18 | +class Solution { |
| 19 | +public: |
| 20 | + int maxSumSubmatrix(vector<vector<int>>& matrix, int k) { |
| 21 | + int row = matrix.size(); |
| 22 | + int col = row == 0 ? 0 : matrix[0].size(); |
| 23 | + vector<vector<int> > sum_mat(row+1, vector<int>(col+1, 0)); |
| 24 | + for(int i=1; i<=row; i++){ |
| 25 | + for(int j=1; j<=col; j++){ |
| 26 | + sum_mat[i][j] = sum_mat[i-1][j] + sum_mat[i][j-1] - sum_mat[i-1][j-1] + matrix[i-1][j-1]; |
| 27 | + } |
| 28 | + } |
| 29 | + int n = (row+1)*(col+1); |
| 30 | + vector<vector<int> > cache(n, vector<int>(n, INT_MIN)); |
| 31 | + int left = 0; |
| 32 | + int right = row*col-1; |
| 33 | + return sum_util(sum_mat, left, right, cache, k); |
| 34 | + } |
| 35 | + |
| 36 | + int sum_util(vector<vector<int> >& sum_mat, int left, int right, vector<vector<int> >& cache, int& k){ |
| 37 | + if(left > right){ |
| 38 | + return INT_MIN; |
| 39 | + } |
| 40 | + int cols = sum_mat[0].size() -1 ; |
| 41 | + int row1 = left / cols; |
| 42 | + int col1 = left % cols; |
| 43 | + |
| 44 | + int row2 = right / cols; |
| 45 | + int col2 = right % cols; |
| 46 | + |
| 47 | + if(row1 > row2 || col1 > col2){ |
| 48 | + return INT_MIN; |
| 49 | + } |
| 50 | + |
| 51 | + if(cache[left][right] != INT_MIN){ |
| 52 | + return cache[left][right]; |
| 53 | + } |
| 54 | + |
| 55 | + return cache[left][right] = max(max(is_bigger(sum_mat[row2+1][col2+1] - sum_mat[row2+1][col1] - sum_mat[row1][col2+1] + sum_mat[row1][col1],k), |
| 56 | + sum_util(sum_mat, left+1, right, cache, k)), sum_util(sum_mat, left, right-1, cache, k)); |
| 57 | + } |
| 58 | + |
| 59 | + int is_bigger(int sum, int k){ |
| 60 | + if(sum > k) |
| 61 | + return INT_MIN; |
| 62 | + else |
| 63 | + return sum; |
| 64 | + } |
| 65 | +}; |
| 66 | + |
| 67 | + |
| 68 | +// 2D Kadane's algorithm |
| 69 | +// This method has a bug, the reason is that comparison with k cannot be done in main func, |
| 70 | +// it should be done in max_util.Because if max is over k, we should discard the res all, |
| 71 | +// we should reserve part of it. |
| 72 | +class Solution { |
| 73 | +public: |
| 74 | + int maxSumSubmatrix(vector<vector<int>>& matrix, int k) { |
| 75 | + int row = matrix.size(); |
| 76 | + int col = row==0?0:matrix[0].size(); |
| 77 | + if(row == 0){ |
| 78 | + return 0; // seem like 0 is not a good return |
| 79 | + } |
| 80 | + int max_so_far=INT_MIN, cur_sum=0; |
| 81 | + int max_left=-1, max_right=-1, max_up=-1, max_down=-1; |
| 82 | + int L=0, R=0; |
| 83 | + // Row-wise to implement Kadane's algorithm. |
| 84 | + vector<int> per_col(row, 0); // if the rows >> cols, otherwise per_row(matrix[0].size()). |
| 85 | + // Time complexity is O(col*col*row), space O(row) |
| 86 | + for(L=0; L<col; L++){ |
| 87 | + for(R=L; R<col; R++){ |
| 88 | + add_col(row, R, matrix, per_col); |
| 89 | + vector<int> max_vec = max_util(per_col); |
| 90 | + if(max_vec[2] > max_so_far && max_vec[2] <= k){ |
| 91 | + max_so_far = max_vec[2]; |
| 92 | + max_up = max_vec[0]; |
| 93 | + max_down = max_vec[1]; |
| 94 | + max_left = L; |
| 95 | + max_right = R; |
| 96 | + } |
| 97 | + } |
| 98 | + per_col.assign(per_col.size(), 0); |
| 99 | + } |
| 100 | + return max_so_far; |
| 101 | + |
| 102 | + } |
| 103 | + void add_col(int row, int col_index, vector<vector<int> >& matrix, vector<int>& per_col){ |
| 104 | + for(int i=0; i<row; i++){ |
| 105 | + per_col[i] += matrix[i][col_index]; |
| 106 | + } |
| 107 | + } |
| 108 | + vector<int> max_util(vector<int>& nums){ |
| 109 | + int max_so_far=INT_MIN, sum_here = 0; |
| 110 | + int s=0, start=0, end=0; |
| 111 | + for(int i=0; i<nums.size(); i++){ |
| 112 | + sum_here = sum_here + nums[i]; |
| 113 | + if(sum_here > max_so_far){ |
| 114 | + max_so_far = sum_here; |
| 115 | + start = s; |
| 116 | + end = i; |
| 117 | + } |
| 118 | + if(sum_here < 0){ |
| 119 | + sum_here = 0; |
| 120 | + s = i+1; // update start, from next num to the negative sum. |
| 121 | + } |
| 122 | + } |
| 123 | + vector<int> res(3, 0); |
| 124 | + res[0] = start; |
| 125 | + res[1] = end; |
| 126 | + res[2] = max_so_far; |
| 127 | + return res; |
| 128 | + } |
| 129 | +}; |
| 130 | + |
| 131 | + |
| 132 | + |
| 133 | + |
| 134 | + |
| 135 | +class Solution { |
| 136 | +public: |
| 137 | + int maxSumSubmatrix(vector<vector<int>>& matrix, int k) { |
| 138 | + int row = matrix.size(); |
| 139 | + int col = row==0?0:matrix[0].size(); |
| 140 | + if(row == 0){ |
| 141 | + return 0; // seem like 0 is not a good return |
| 142 | + } |
| 143 | + int max_so_far=INT_MIN, cur_sum=0; |
| 144 | + int max_left=-1, max_right=-1, max_up=-1, max_down=-1; |
| 145 | + int L=0, R=0; |
| 146 | + // Row-wise to implement Kadane's algorithm. |
| 147 | + vector<int> per_col(row, 0); // if the rows >> cols, otherwise per_row(matrix[0].size()). |
| 148 | + // Time complexity is O(col*col*row), space O(row) |
| 149 | + for(L=0; L<col; L++){ |
| 150 | + for(R=L; R<col; R++){ |
| 151 | + add_col(row, R, matrix, per_col); |
| 152 | + // vector<int> max_vec = max_util(per_col); |
| 153 | + cur_sum = max_util_no_lager_than_K(per_col, k); |
| 154 | + if(cur_sum > max_so_far){ |
| 155 | + max_so_far = cur_sum; |
| 156 | + } |
| 157 | + } |
| 158 | + per_col.assign(per_col.size(), 0); |
| 159 | + } |
| 160 | + return max_so_far; |
| 161 | + |
| 162 | + } |
| 163 | + void add_col(int row, int col_index, vector<vector<int> >& matrix, vector<int>& per_col){ |
| 164 | + for(int i=0; i<row; i++){ |
| 165 | + per_col[i] += matrix[i][col_index]; |
| 166 | + } |
| 167 | + } |
| 168 | + int max_util_no_lager_than_K(vector<int>& nums, int k){ |
| 169 | + set<int> s; |
| 170 | + s.insert(0); |
| 171 | + int max_res = 0; |
| 172 | + int cur_sum=0; |
| 173 | + for(auto& i: nums){ |
| 174 | + cur_sum += i; |
| 175 | + auto it = s.lower_bound(cur_sum-k); |
| 176 | + // start = it, end = i.index |
| 177 | + if(it != s.end()) max_res = max(max_res, cur_sum-*it); |
| 178 | + s.insert(cur_sum); |
| 179 | + } |
| 180 | + return max_res; |
| 181 | + } |
| 182 | +}; |
| 183 | + |
0 commit comments