Maximum Side Length of a Square with Sum Less than or Equal to Threshold
程序员文章站
2024-03-06 21:29:38
...
Given a m x n
matrix mat
and an integer threshold
. Return the maximum side-length of a square with a sum less than or equal to threshold
or return 0 if there is no such square.
Example 1:
Input: mat = [[1,1,3,2,4,3,2],[1,1,3,2,4,3,2],[1,1,3,2,4,3,2]], threshold = 4 Output: 2 Explanation: The maximum side length of square with sum less than 4 is 2 as shown.
Example 2:
Input: mat = [[2,2,2,2,2],[2,2,2,2,2],[2,2,2,2,2],[2,2,2,2,2],[2,2,2,2,2]], threshold = 1 Output: 0
Example 3:
Input: mat = [[1,1,1,1],[1,0,0,0],[1,0,0,0],[1,0,0,0]], threshold = 6 Output: 3
Example 4:
Input: mat = [[18,70],[61,1],[25,85],[14,40],[11,96],[97,96],[63,45]], threshold = 40184 Output: 2
Constraints:
1 <= m, n <= 300
m == mat.length
n == mat[i].length
0 <= mat[i][j] <= 10000
0 <= threshold <= 10^5
思路:build 矩阵的prefixsum ,记住建立的时候是 sum[i][j - 1] + sum[i - 1][j] - sum[i - 1][j - 1] + mat[i - 1][j - 1];
利用prefixsum求正方形的时候是:sum[i][j] - sum[i - len][j] - sum[i][j - len] + sum[i - len][j - len]
建立好prefixsum之后,在0,math.min(n,m)之间做binary search, T: n * m * log(min(n,m));
class Solution {
public int maxSideLength(int[][] mat, int threshold) {
int n = mat.length;
int m = mat[0].length;
int[][] sum = new int[n + 1][m + 1];
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
sum[i][j] = sum[i][j - 1] + sum[i - 1][j] - sum[i - 1][j - 1] + mat[i - 1][j - 1];
}
}
int start = 0; int end = Math.min(n, m);
while(start + 1 < end) {
int mid = start + (end - start) / 2;
if(canhave(mat, mid, threshold, sum)) {
start = mid;
} else {
end = mid;
}
}
if(canhave(mat, end, threshold, sum)) {
return end;
}
if(canhave(mat, start, threshold, sum)) {
return start;
}
return 0;
}
private boolean canhave(int[][] mat, int len, int threshold, int[][] sum) {
for(int i = len; i <= mat.length; i++) {
for(int j = len; j <= mat[0].length; j++) {
if(sum[i][j] - sum[i - len][j] - sum[i][j - len] + sum[i - len][j - len] <= threshold) {
return true;
}
}
}
return false;
}
}
思路2:这个比较巧妙,就是在建立prefixsum 矩阵的时候,一起判断,是否有比len更大的合法正方形,有就len++;O(m * n);
class Solution {
public int maxSideLength(int[][] mat, int threshold) {
int n = mat.length;
int m = mat[0].length;
int[][] sum = new int[n + 1][m + 1];
int res = 0;
int len = 1;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + mat[i - 1][j - 1];
if(i - len >= 0 && j - len >= 0 &&
sum[i][j] - sum[i - len][j] - sum[i][j - len] + sum[i - len][j - len] <= threshold) {
res = len++;
}
}
}
return res;
}
}