You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

78 lines
1.9 KiB

2 years ago
package class46;
import java.util.TreeSet;
public class Problem_0363_MaxSumOfRectangleNoLargerThanK {
public static int nearK(int[] arr, int k) {
if (arr == null || arr.length == 0) {
return Integer.MIN_VALUE;
}
TreeSet<Integer> set = new TreeSet<>();
set.add(0);
int ans = Integer.MIN_VALUE;
int sum = 0;
for (int i = 0; i < arr.length; i++) {
// 讨论子数组必须以i位置结尾最接近k的累加和是多少
sum += arr[i];
// 找之前哪个前缀和 >= sum - k 且最接近
// 有序表中ceiling(x) 返回>=x且最接近的
// 有序表中floor(x) 返回<=x且最接近的
Integer find = set.ceiling(sum - k);
if(find != null) {
int curAns = sum - find;
ans = Math.max(ans, curAns);
}
set.add(sum);
}
return ans;
}
public static int maxSumSubmatrix(int[][] matrix, int k) {
if (matrix == null || matrix[0] == null) {
return 0;
}
if (matrix.length > matrix[0].length) {
matrix = rotate(matrix);
}
int row = matrix.length;
int col = matrix[0].length;
int res = Integer.MIN_VALUE;
TreeSet<Integer> sumSet = new TreeSet<>();
for (int s = 0; s < row; s++) {
int[] colSum = new int[col];
for (int e = s; e < row; e++) {
// s ~ e 这些行 选的子矩阵必须包含、且只包含s行~e行的数据
// 0 ~ 0 0 ~ 1 0 ~ 2 。。。
// 1 ~ 2 1 ~ 2 1 ~ 3 。。。
sumSet.add(0);
int rowSum = 0;
for (int c = 0; c < col; c++) {
colSum[c] += matrix[e][c];
rowSum += colSum[c];
Integer it = sumSet.ceiling(rowSum - k);
if (it != null) {
res = Math.max(res, rowSum - it);
}
sumSet.add(rowSum);
}
sumSet.clear();
}
}
return res;
}
public static int[][] rotate(int[][] matrix) {
int N = matrix.length;
int M = matrix[0].length;
int[][] r = new int[M][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
r[j][i] = matrix[i][j];
}
}
return r;
}
}