zoukankan      html  css  js  c++  java
  • 1074. Number of Submatrices That Sum to Target

    问题:

    给定一个二维数组,求子数组之和为target的子数组个数。

    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.
     
    
    Note:
    1 <= matrix.length <= 300
    1 <= matrix[0].length <= 300
    -1000 <= matrix[i] <= 1000
    -10^8 <= target <= 10^8
    

      

    解法:

    560. Subarray Sum Equals K

    解法说明

    是上述题目的延展,思想一致。

    一个数列:Target = Sum(i~j)  =Sum(0~j)-Sum(0~i)    =Sum(j)-Sum(i)

    所以:Sum(i) = Sum(j)-Target

    那么 直到 第j个元素:和为target的子数组个数cout(sum=target) = cout(sum=当前sum(j)-Target) 到j为止,前缀和(0~x)为(sum(j)-Target)的子数组个数。

    再考虑:二维数组->降维

    固定列(or行,这里我们选择列),

    从内部看:对于每一组列(j,k)<第j列到第k列为一组>,幻化成单列,内部进行上面的算法操作。

    ★幻化成单列:单列里的每个元素=matrix[..][j]+...+matrix[..][k]=Sum(matrix[..][k])-Sum(matrix[..][j-1])

    从外部看:要求的子数组,即是将每一组列看作一个整体,各自得出的子数组数,累加即可

    每一组列:左右(j,k)两个bound来界定,00,01,02,03,...,0m, 11,12,13,...,1m,...,(m-1)m, mm

    为了求★的Sum(matrix[..][k]),进行第一轮for循环,

    1         for(i=0; i<n; i++){
    2             for(j=1; j<m; j++){
    3                 matrix[i][j]+=matrix[i][j-1];
    4             }
    5         }

    然后,固定列,排列组合各种组列:

    (每一组列:左右(j,k)两个bound来界定,00,01,02,03,...,0m, 11,12,13,...,1m,...,(m-1)m, mm)

    1         for(j=0; j<m; j++){
    2             for(k=j; k<m; k++){
    3                 sumhash={{0,1}};
    4                 int presum=0;
    5                 ......
    6                 }
    7             }
    8         }

    对每一组列,遍历每个元素(row压缩为一个:matrix[..][k]-matrix[..][j-1])

    累加,计算前缀和presum。并保存前缀和计数map:sumhash中。

    1                 for(i=0; i<n; i++){
    2                     presum+=(matrix[i][k]-(j>0?matrix[i][j-1]:0));
    3                     ......
    4                     sumhash[presum]++;
    5                 }

    对于到目前的 i,为止,sum=target的子数列数目= 前缀和为 当前总和-target 的前缀数组个数。

    1                     res+=sumhash.find(presum - target) != sumhash.end() ? sumhash[presum - target] : 0;

    代码参考:

    ⚠️注意:不用●的写法,而使用count判断存在与否,在进行赋值,减少运算时间。

     1 class Solution {
     2 public:
     3     int numSubmatrixSumTarget(vector<vector<int>>& matrix, int target) {
     4         int i=0, j=0, k=0;
     5         int n=matrix.size(), m=matrix[0].size();
     6         int res=0;
     7             //  |0| 1 |  2  |   3   |
     8             //->|0|0+1|0+1+2|0+1+2+3|★
     9         for(i=0; i<n; i++){
    10             for(j=1; j<m; j++){
    11                 matrix[i][j]+=matrix[i][j-1];
    12             }
    13         }
    14         unordered_map<int,int>sumhash;
    15         for(j=0; j<m; j++){
    16             for(k=j; k<m; k++){
    17                 sumhash={{0,1}};
    18                 int presum=0;
    19                 // col-j ~ col-k fixed.  move row
    20                 // cause ★, so only to see → value.(matrix[..][k])
    21                 // remove 0~j-1 cols, so -matrix[..][j-1]
    22                 for(i=0; i<n; i++){
    23                     presum+=(matrix[i][k]-(j>0?matrix[i][j-1]:0));
    24                     res+=sumhash.find(presum - target) != sumhash.end() ? sumhash[presum - target] : 0;
    25                         //●sumhash[presum-target];//k:sum(x), v:cout(sum(x))
    26                     //target=sum(i~j)=sum(j)-sum(i)
    27                     //sum(i)=sum(j)-target
    28                     //until j: cout(sum=target)=cout(sum=sum(i))
    29                     sumhash[presum]++;
    30                 }
    31             }
    32         }
    33         return res;
    34     }
    35 };
  • 相关阅读:
    python 练习洗牌
    python 生成二维码
    转载 HTTP协议
    分别使用python和java练习冒泡排序
    python-字符串
    [转]三层架构与MVC之间的区别
    [转]JAVA异常
    [转]JavaEE开发基础
    [转]JAVA对象容器
    数据库操作实例
  • 原文地址:https://www.cnblogs.com/habibah-chang/p/12905060.html
Copyright © 2011-2022 走看看