矩陣字首和。因為矩陣中可能包含負值,所以這題肯定不會存在什麼剪枝,動態規劃的可能性。所以這個題也就沒什麼彎彎繞繞。個人感覺算不上個Hard題目。

最直觀的思路就是列舉子矩陣,既列舉矩陣的左上角節點和右下角節點所構成的子矩陣。列舉是4層迴圈。

然後矩陣和的計算是兩層迴圈,肯定不能套在列舉子矩陣的迴圈裡。

我們維護一個矩陣字首和,即prefix[p][q]是左上角0,0節點和右下角p,q節點構成矩陣的面積和。

那麼對於任意矩陣:(i,j)(p,q),其矩陣和 = prefix[p][q] – prefix[i-1][q] – prefix[p][j-1] + prefix[i-1][j-1]

可以在紙上畫一下圖,一下子就能看明白了。

最終的時間複雜度為O(n^4)

1074. 元素和為目標值的子矩陣數量

class Solution {
public int numSubmatrixSumTarget(int[][] matrix, int target) {
int m = matrix.length;
if (m == 0) {
return 0;
}
int n = matrix[0].length; int[][] f = new int[m][n];
for (int i = 0; i<m ;i++) {
f[i][0] = matrix[i][0];
for (int j = 1; j<n ; j++) {
f[i][j] = f[i][j-1] + matrix[i][j];
}
} // 左上角為0,0;右下角為i,j
int[][] prefixSum = new int[m][n];
for (int i=0;i<m;i++) {
for (int j=0;j<n;j++) {
if (i>0) {
prefixSum[i][j] = prefixSum[i-1][j];
}
prefixSum[i][j] += f[i][j];
}
} int ans = 0;
for (int i=0;i<m;i++) {
for (int j=0;j<n;j++) {
for (int p = i;p<m;p++) {
for (int q=j;q<n;q++) {
int sum = prefixSum[p][q];
if (i>0) {
sum -= prefixSum[i-1][q];
}
if (j>0) {
sum -= prefixSum[p][j-1];
}
if (i>0&&j>0) {
sum += prefixSum[i-1][j-1];
} if (sum == target) ans++;
}
}
}
} return ans;
}
}