首页 > 其他分享 >“前缀和”专题篇二

“前缀和”专题篇二

时间:2024-08-16 08:54:55浏览次数:9  
标签:专题 前缀 int sum 位置 计算 数组

目录

和为K的子数组

和可被K整除的子数组

连续数组

矩阵区域和


和为K的子数组

题目

思路

我们可能想到的是,从头到尾扫描数组,然后分别计算以该位置为开始,一直到数组末尾,符合和为K的子数组,但是这种方法的时间复杂度是O(N^2),是会超时的,因此需要别的方法来解决。

可能又会想到利用“前缀和”的思想,但是从头到尾扫描整个数组,然后分别计算以该位置为开始,一直到数组末尾,符合和为K的子数组,这样时间复杂度依旧是O(N^2),是会超时的,因此需要别的方法来解决。

下面我们仔细分析一下,子数组问题可以通过以某个位置为结尾来分析,此时可以先计算出该位置(含该位置)之前所有数的和,这个和是确定的,要想找到以该位置为结尾且和为K的子数组,只需要找出该位置之前和为sum-K的子数组即可,该位置之前和为sum-K的子数组的数量,就是以该位置为结尾且和为K的子数组的个数,这里可以使用“前缀和”思想,不过这里存储的不再单单只是元素的和,而是每个元素的和以及对应的个数,这里需要注意的一点是,我们并不是提前计算好前缀和,而是分析到哪个位置就计算到哪个位置之前的前缀和以及其对应的个数,可以使用哈希表进行存储,方便及时查询到,并且我们可以做一些优化,因为计算前缀和只需要知道前一个位置的前缀和,因此使用一个变量就可以实现计算前缀和。

还有需要注意的是,针对上面的方法,如果所求整个数组的和为sum,那么我们会计算[0,-1]区间的数组的和,因此,我们需要考虑到这一点,处理方法是先将0存放到哈希表中,映射的值是1.

代码

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        unordered_map<int,int> hash;
        hash[0]=1;
        int sum=0,ret=0;
        for(int x:nums){
            sum+=x;
            if(hash.count(sum-k)) ret+=hash[sum-k];
            hash[sum]++;
        }
        return ret;
    }
};
和可被K整除的子数组

题目

思路

我们可能想到的是,从头到尾扫描数组,然后分别计算以该位置为开始,一直到数组末尾,符合和可被K整除的子数组,但是这种方法的时间复杂度是O(N^2),是会超时的,因此需要别的方法来解决。

可能又会想到利用“前缀和”的思想,但是从头到尾扫描整个数组,然后分别计算以该位置为开始,一直到数组末尾,符合和可被K整除的子数组,这样时间复杂度依旧是O(N^2),是会超时的,因此需要别的方法来解决。

下面我们仔细分析一下,子数组问题可以通过以某个位置为结尾来分析,此时我们可以先计算该位置(含该位置)之前所有元素的和,题目要求是找出和可被K整除的子数组,因为该位置(含该位置)之前所有元素的和是确定的,如果找出以该位置为结尾,和可被K整除的子数组,假设该位置(含该位置)之前所有元素的和是sum,除了和可被K整除的子数组之外元素的和是sum-n*k,那么根据《同余定理》就有sum%k=(sum-n*k),即我们只需找出该位置之前余数为sum%K的子数组的个数即可,这里需要注意的是,我们不再是先提前计算好前缀和,而是求到哪个位置就计算到哪个位置的前缀和,这里使用变量来代替之前的数组,因为计算前缀和只会用到前一个位置的前缀和和当前位置的元素,并且这里不再只是计算前缀和,还需要计算每个前缀和的值的余数对应的个数,使用哈希表来进行存储,这样就可以更快地查询到每个前缀和的值的余数对应的个数。

因为C++中对负数取模,得到的还是一个负数,因此我们需要做一些处理,即针对sum%K,变换成(sum%K+K)%K。

还有需要注意的是,针对上面的方法,如果所求整个数组的和为sum,那么我们会计算[0,-1]区间的数组余数为(sum%K+K)%K的个数,因此,我们需要考虑到这一点,处理方法是先将0存放到哈希表中,映射的值是1.

代码

class Solution {
public:
    int subarraysDivByK(vector<int>& nums, int k) {
        unordered_map<int,int> hash;
        hash[0%k]=1;
        int sum=0,ret=0;
        for(int x:nums){
            sum+=x;
            int a=(sum%k+k)%k;
            if(hash.count(a)) ret+=hash[a];
            hash[a]++;
        }
        return ret;
    }
};
连续数组

题目

思路

我们可能想到利用“前缀和”的思想,但是这道题是01序列,利用“前缀和”思想并不能知道具体有多少个0,因此我们需要再分析分析,我们不妨将原始数组中的0替换成 -1,这样找出的数组是1和 -1能够相互抵消的。

解决这道题时,我们使用“前缀和”时,不能先提前计算好前缀和,而是分析到哪个位置就把前缀和计算到哪个位置,因为计算每个位置的前缀和只会用到前一个位置的前缀和以及当前位置的值。

需要注意的是,因为题目要求含有相同数量的01的子数组的最长长度,因此下面在计算前缀和时还需要记录每个前缀和值对应的区间末尾最小下标,即如果再次遇到相同前缀和值的时候,不再记录,只记录前缀和值首次出现的区间末尾下标。

代码

class Solution {
public:
    int findMaxLength(vector<int>& nums) {
        unordered_map<int,int> hash;
        hash[0]=-1;
        int sum=0,ret=0;
        for(int i=0;i<nums.size();i++){
            sum+=nums[i]==0?-1:1;
            if(hash.count(sum)) ret=max(ret,i-hash[sum]);
            else hash[sum]=i;
        }
        return ret;
    }
};
矩阵区域和

题目

思路

这道题如果使用暴力解法的话,即针对针对查询,算出本次查询的区域,然后再计算出该区域所有数的和,但是这种方法的时间复杂度是O(N*M*Q),是会超时的,因此需要别的方法来解决。

下面将依旧使用“前缀和”的思想来解决这道题,即预先计算出每个位置和左上角构成的矩形的值的总和,针对每次查询,就可以使用O(1)的时间复杂度计算出所查询区域的值的总和。

【1】计算好每个位置和左上角构成的矩形的值的总和

【2】计算出所查询区域的值的总和

其实快速解决这道题是利用二维前缀和,只不过这道题要处理一些边界情况,因为下标[i-k],[i+k],[j-k],[j+k]是有可能超过二维前缀和矩阵的大小的,需要特别处理一下。

代码

class Solution {
public:
    vector<vector<int>> matrixBlockSum(vector<vector<int>>& mat, int k) {
        int m=mat.size(),n=mat[0].size();
        vector<vector<int>> dp(m+1,vector<int>(n+1));
        vector<vector<int>> answer(m,vector<int>(n));
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
                dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+mat[i-1][j-1];
        for(int i=0;i<m;i++)
            for(int j=0;j<n;j++){
                int x1=max(1,i-k+1),y1=max(1,j-k+1);
                int x2=min(m,i+k+1),y2=min(n,j+k+1);
                answer[i][j]=dp[x2][y2]-dp[x1-1][y2]-dp[x2][y1-1]+dp[x1-1][y1-1];
                // answer[i][j]=dp[min(m,i+k+1)][min(n,j+k+1)]-dp[max(0,i-k)][min(n,j+k+1)]-dp[min(m,i+k+1)][max(0,j-k)]+dp[max(0,i-k)][max(0,j-k)];
            }
        return answer;
    }
};

标签:专题,前缀,int,sum,位置,计算,数组
From: https://blog.csdn.net/wmh_1234567/article/details/140594877

相关文章

  • (路由卷1)-37-前缀列表_K1_IGP分析
    ipprefix前缀列表r2:routerospf1network10.0.0.8area0redistributeriproute-mapintoospfsubnetsrouterripnet10.0.0.0ver2passive-inters3redistributeospf1route-mapintoripmetric5route-mapintoospfpermit10matchipaddressprefix-listpf......
  • 【代码随想录】一、数组:6.前缀和
    二刷的时候发现更新了一些新的题目,尝试写了写后,发现我完全不会ACM输入输出模式。这两天在补前几天没背的八股,写得不够满意(几乎是完全誊代码了),先放着,后面再补充补充吧。1.题目:44.开发商购买土地#include<iostream>#include<vector>#include<climits>usingnamespacestd......
  • D44 2-SAT+前缀优化+二分 CF587D Duff in Mafia
    视频链接: CF587DDuffinMafia-洛谷|计算机科学教育新生态(luogu.com.cn)#include<iostream>#include<cstring>#include<algorithm>#include<vector>usingnamespacestd;constintN=500005;inthead[N],idx,ne[N*6],to[N*6];voidadd(intx,......
  • 专题(二)比较
    -eq相等(equal)-ne不等(notequal)-gt大于(greaterthan)-lt小于(lessthan)-ge大于等于(greaterthanorequal)-le小于等于(lessthanorequal)1、字符串比较[ $str1 = $str2 ]等于[ $str1 != $str2 ]不等于[-z $str ]空字符串返回true[-n $str ]或者[ $str......
  • D43 2-SAT+前缀优化 P6378 [PA2010] Riddle
    视频链接: P6378[PA2010]Riddle-洛谷|计算机科学教育新生态(luogu.com.cn)//2-SAT+前缀优化O(n+m)#include<iostream>#include<cstring>#include<algorithm>usingnamespacestd;#definex0(x)x//点#definex1(x)x+n//反点#definep0(x)x+2*n......
  • 【专题】2024无人驾驶网约车乘坐意愿调查报告合集PDF分享(附原数据表)
     原文链接:https://tecdat.cn/?p=37335 科技迅猛发展,无人驾驶技术从科幻走进现实,2024年无人驾驶网约车成热议话题。阅读原文,获取专题报告合集全文,解锁文末208份无人驾驶网约车相关行业研究报告。报告表明,近60%受访者期待,00后更积极,80后较谨慎。性别上男性更乐观,城市级别......
  • 前缀和
    1前缀和练习1)跳楼机人数安排题目点击查看代码中文解释#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong#definedbg(x)cout<<#x<<'='<<x<<endlconstintN=2e5+15;intn,m,q[N],a[N];signedmain(){......
  • 长度最小的子数组 | LeetCode-209 | 双指针+滑动窗口 | 前缀和+二分查找 | Java详细注
    ......
  • 二维前缀和学习指南
    为什么我为OI泪目,因为我菜得离谱......二维前缀和引子二维前缀和,仅仅是由一维前缀和进阶了一维而已。为了方便后面的学习,我先给出二维前缀和重点代码。处理二维前缀和for(inti=1;i<=n;i++) for(intj=1;j<=m;j++) sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[......
  • 专题 (五) map 数据结构
    1、用法用法说明1、declare-Amap2、declare-AmyMap=(["my01"]="01"["my02"]="02")3、declare-Amap=()1、声明map变量2、声明map变量的同时可以赋值3、定义一个空mapmap[$_key]=$_count指定key赋值value,其中_key和_value均是shenll变量1、e......