每日一题
今天的每日一题确实让博主我伤透脑筋 :x
闲话不多说~ 来人! 上图!
看完题目的我,也不准备重拳出击了,代码能过就好…
首先来分析题目
大致意思呢就是 ,他要让我们拿所有可能的子矩阵的sum值和target比较,通过计数来得出有多少子矩阵的sum值。
第一步
通过二维数组前缀和得把这个子矩阵的sum值拿到我们把每个方块比作矩阵中的1个元素,那么这个矩阵的sum值可由 S(红色) + S(蓝色) - S(红蓝) + S(黄色对勾) 得到。这里的S就代表了子矩阵元素的sum值。
如果解释的还不够清楚,下面我附上官方解释…
第二步
通过切割得到任一子矩阵的sum值(子矩阵位置不定)
看了我的解释和官方的解释,肯定有人和我当初一样有疑惑:怎么把所有子矩阵的sum值都遍历一遍呢?
我只想到了暴力,毕竟一力降十会hhhh
对于不同位置的子矩阵,我们可以通过切割来计算它的sum值
就比如我要求紫色对勾这个子矩阵的sum值(想象里面存在元素…)就可以类比上面的公式得出
S(4) - S(3) - S(2) + S(1) 这里S同样是矩阵元素的sum值。
下面附上代码块
比较暴力…毕竟一力降十会hhh
class Solution {
public int numSubmatrixSumTarget(int[][] matrix, int target) {
int[][] sums = new int[matrix.length+1][matrix[0].length+1];
for(int i = 1; i < sums.length; ++i){
for(int j = 1; j < sums[0].length; ++j){
sums[i][j] = sums[i-1][j] + sums[i][j-1] - sums[i-1][j-1]+matrix[i-1][j-1];
}
}
int res = 0;
for(int i = 1; i < sums.length; ++i){
for(int j = 1; j < sums[0].length; ++j){
for(int k = 0; k < i; ++k){
for(int t = 0; t < j; ++t){
if((sums[i][j]-sums[k][j]-sums[i][t]+sums[k][t]) == target){
res++;
}
}
}
}
}
return res;
}
}
要注意for循环里面的i,j限制条件…(卡在这了好久)
补充
第一步还可以用一维数组的前缀和进行计算,详细可见leetcode304
这里不多赘述。
官方正解
class Solution {
public int numSubmatrixSumTarget(int[][] matrix, int target) {
int ans = 0;
int m = matrix.length, n = matrix[0].length;
for (int i = 0; i < m; ++i) { // 枚举上边界
int[] sum = new int[n];
for (int j = i; j < m; ++j) { // 枚举下边界
for (int c = 0; c < n; ++c) {
sum[c] += matrix[j][c]; // 更新每列的元素和
}
ans += subarraySum(sum, target);
}
}
return ans;
}
public int subarraySum(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
map.put(0, 1);
int count = 0, pre = 0;
for (int x : nums) {
pre += x;
if (map.containsKey(pre - k)) {
count += map.get(pre - k);
}
map.put(pre, map.getOrDefault(pre, 0) + 1);
}
return count;
}
}
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/number-of-submatrices-that-sum-to-target/solution/yuan-su-he-wei-mu-biao-zhi-de-zi-ju-zhen-8ym2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
确实没想到用哈希表来做…
水平还是不够…