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 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 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; } }