[LeetCode] 1074. Number of Submatrices That Sum to Target 元素和為目標值的子矩陣數量



Given a matrix and a target, return the number of non-empty submatrices that sum to target.

A submatrix x1, y1, x2, y2 is the set of all cells matrix[x][y] with x1 <= x <= x2 and y1 <= y <= y2.

Two submatrices (x1, y1, x2, y2) and (x1', y1', x2', y2') are different if they have some coordinate that is different: for example, if x1 != x1'.

Example 1:

Input: matrix = [[0,1,0],[1,1,1],[0,1,0]], target = 0
Output: 4
Explanation: The four 1x1 submatrices that only contain 0.

Example 2:

Input: matrix = [[1,-1],[-1,1]], target = 0
Output: 5
Explanation: The two 1x2 submatrices, plus the two 2x1 submatrices, plus the 2x2 submatrix.

Example 3:

Input: matrix = [[904]], target = 0
Output: 0

Constraints:

  • 1 <= matrix.length <= 100
  • 1 <= matrix[0].length <= 100
  • -1000 <= matrix[i] <= 1000
  • -10^8 <= target <= 10^8

這道題給了一個二維矩陣 matrix 和一個整型數 target,問有多少個非空的子矩陣使得其和正好等於 target。首先來想,這道題身為 Hard 難度,肯定不能用暴力搜索,博主之前也屢次強調過,這是一種不尊重,會慘遭 OJ 的毒打。既然是要求子矩陣之和的問題,就來想想有沒有什么方法可以快速求得子矩陣之和,博主馬上就聯想到了之前在求子數組之和時,可以通過建立累加和數組來快速的求出任意的子數組之和。這里也可以利用相同的思路,只不過是建立的是累加和矩陣,從一維升級到了二維而已,為的就是以空間來換取時間。建立的方法比一維的稍稍復雜一些,大小為 (m+1)x(n+1),多出一位可以避免越界,然后從1開始遍歷,當前位置的累加和等於上面的值加上左邊的值減去左上方的值,最后加上原數組中當前位置的值,這樣整個累加和矩陣就建立好了。接下來就要遍歷所有子矩陣了,由於矩陣有四個端點,所以遍歷是四次方的時間復雜度,不過好在有累加和矩陣,只要四個端點坐標確定了,可以在常數級的時間復雜度內求出子矩陣之和,若這個值等於 target,則結果 res 自增1即可。這個方法基本上是壓線過的 OJ,多虧 OJ 仁慈,放了一馬,參見代碼如下:


解法一:

class Solution {
public:
    int numSubmatrixSumTarget(vector<vector<int>>& matrix, int target) {
        int res = 0, m = matrix.size(), n = matrix[0].size();
        vector<vector<int>> sums(m + 1, vector<int>(n + 1));
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                sums[i][j] = sums[i][j - 1] + sums[i - 1][j] - sums[i - 1][j - 1] + matrix[i - 1][j - 1];
            }
        }
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                for (int p = 1; p <= i; ++p) {
                    for (int q = 1; q <= j; ++q) {
                        int t = sums[i][j] - sums[i][q - 1] - sums[p - 1][j] + sums[p - 1][q - 1];
                        if (t == target) ++res;
                    }
                }
            }
        }
        return res;
    }
};

上面方法其實沒有太多的技巧,硬說是 Hard 的難度有些牽強,再來看一種論壇上的高分解法,一種真正符合其身價的解法。這種解法的思路在之前的 Subarray Sum Equals KMax Sum of Rectangle No Larger Than K 其實都出現過,有點 Two Sum 的影子在里面。話說 Two Sum 可是博主刷的第一道題呢,那個一個陽光明媚的下午,博主安靜地坐在圖書館中,打開了心愛的小 Mac,登進了朋友推薦的 LeetCode 網站,從此便和力扣結下了不解之緣。如今已經刷了上千道題了,成了大家眼中的千條哥了。好了,打住打住,回到題目,具體的思路是,先建立每一行的累加和數組,這里其實將矩陣微積分化了,看作是多行的累加,有了行的累加和數組,就可以快速知道每一行的子數組之和了。接下來只要確定行的寬度就行了,即遍歷任意兩個列,它們之間的距離就是子矩陣的寬,然后新建一個 HashMap,建立子矩陣之和跟其出現次數之間的映射,初識時將 0->1 這個映射對兒加入,后面會講原因。然后新建一個變量 cur,接下來遍歷所有行,由於子矩陣的寬已經確定了,遍歷不同行,就是進一步確定子矩陣的高,這樣就能准確的確定一個子矩陣的范圍了。先利用行的累加和數組來快速求出該行的數字之和,注意為了避免數組越界,需要判斷一下i是否大於0。當前的子矩陣之和求出來后,保存在了 cur 之中,現在要看其和 target 之間的關系,cur 如果小於 target,則無事發生;若大於 target,則看 cur - target 是否存在,若存在,則表示和為 target 的子矩陣也必然存在,且個數跟和為 cur-target 的子矩陣相同,所以結果 res 可以直接加上 cur-target 的映射值。但是還有一種情況,當 cur 正好等於 target 的時候,cur-target 就為0了,這時候 HashMap 中0的映射值若為0,則就沒法加上這種情況了,這就是為啥要將 0->1 這個映射對兒提前加入的原因。最后別忘了將 cur 的映射值自增1,參見代碼如下:


解法二:

class Solution {
public:
    int numSubmatrixSumTarget(vector<vector<int>>& matrix, int target) {
        int res = 0, m = matrix.size(), n = matrix[0].size();
        for (int i = 0; i < m; ++i) {
            for (int j = 1; j < n; ++j) {
                matrix[i][j] += matrix[i][j - 1];
            }
        }
        for (int i = 0; i < n; ++i) {
            for (int j = i; j < n; ++j) {
                unordered_map<int, int> cntMap{{0, 1}};
                int cur = 0;
                for (int k = 0; k < m; ++k) {
                    cur += matrix[k][j] - (i > 0 ? matrix[k][i - 1] : 0);
                    res += cntMap[cur - target];
                    ++cntMap[cur];
                }
            }
        }
        return res;
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1074


類似題目:

Subarray Sum Equals K

Max Sum of Rectangle No Larger Than K

Two Sum


參考資料:

https://leetcode.com/problems/number-of-submatrices-that-sum-to-target/

https://leetcode.com/problems/number-of-submatrices-that-sum-to-target/discuss/303750/JavaC%2B%2BPython-Find-the-Subarray-with-Target-Sum

https://leetcode.com/problems/number-of-submatrices-that-sum-to-target/discuss/303773/C%2B%2B-O(n3)-Simple-1D-Subarray-target-sum-applied-to-2D-array


LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



猜您在找 【leetcode】1074. Number of Submatrices That Sum to Target LeetCode第[15]題(Java):3Sum (三數之和為目標值)——Medium [LeetCode] Find Smallest Letter Greater Than Target 找比目標值大的最小字母 Leetcode練習(Python):二分查找類:第240題:搜索二維矩陣 II:編寫一個高效的算法來搜索 m x n 矩陣 matrix 中的一個目標值 target。該矩陣具有以下特性: 每行的元素從左到右升序排列。 每列的元素從上到下升序排列。 給定一個整數數組 nums 和一個目標值 target,請你在該數組中找出和為目標值的那 兩個 整數,並返回他們的數組下標。 給定一個整數數組 nums 和一個目標值 target,請你在該數組中找出和為目標值的那 兩個 整數,並返回他們的數組下標。 刷題:給定一個整數數組 nums 和一個目標值 target,請你在該數組中找出和為目標值的那 兩個 整數,並返回他們的數組下標。 用js方法給定一個整數數組nums和一個目標值target,在該數組中找出和為目標值的那兩個整數,並返回他們的下標 給定一個整數數組 nums 和一個目標值 target,請你在該數組中找出和為目標值的那 兩個 整數,並返回他們的數組下標。 你可以假設每種輸入只會對應一個答案。但是,你不能重復利用這個數組中同樣的元素。 示例: 給定 nums = [2, 7, 11, 15], target = 9 因為 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1] 給定一個整數數組 nums 和一個目標值 target,求nums和為target的兩個數的下表
 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM