一、Problem
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.
Constraints:
1 <= m, n <= 300
m == mat.length
n == mat[i].length
0 <= mat[i][j] <= 10000
0 <= threshold <= 10^5
二、Solution
方法一:前綴和 +求子矩陣和
class Solution {
public int maxSideLength(int[][] mat, int thre) {
int R = mat.length, C = mat[0].length, mi = Math.min(R, C), s[][] = new int[R+1][C+1];
for (int i = 1; i <= R; i++)
for (int j = 1; j <= C; j++) {
s[i][j] = mat[i-1][j-1] + s[i-1][j] + s[i][j-1] - s[i-1][j-1];
}
int max = 0;
for (int k = 1; k <= mi; k++) //枚舉子矩陣的邊長
for (int i = 1; i <= R; i++)
for (int j = 1; j <= C; j++) {
if (i-k < 0 || j-k < 0)
continue;
int t = s[i][j] - s[i-k][j] - s[i][j-k] + s[i-k][j-k];
if (t <= thre && k > max) {
max = k;
}
}
return max;
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,
方法二:二分優化
由於邊長 k 越大,子矩陣的總和就越大,所以邊長 k 具備單調性質,可以用二分來優化掉枚舉 這一層循環。
class Solution {
int R, C, mi, s[][];
boolean ck(int k, int thre) {
for (int i = 1; i <= R; i++)
for (int j = 1; j <= C; j++) {
if (i-k < 0 || j-k < 0)
continue;
int t = s[i][j] - s[i-k][j] - s[i][j-k] + s[i-k][j-k];
if (t <= thre)
return true;
}
return false;
}
public int maxSideLength(int[][] mat, int thre) {
R = mat.length; C = mat[0].length; s = new int[R+1][C+1];
for (int i = 1; i <= R; i++)
for (int j = 1; j <= C; j++) {
s[i][j] = mat[i-1][j-1] + s[i-1][j] + s[i][j-1] - s[i-1][j-1];
}
int max = 0;
int l = 1, r = Math.min(R, C), res = 0;
while (l <= r) {
int k = l + r >>> 1;
if (ck(k, thre)) {l = k + 1; res = k;}
else r = k - 1;
}
return res;
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,