LeetCode:560 974 数组前缀和

子数组的连续和的问题,可以首先考虑滑动窗口如果滑动窗口不好用,可以使用这里的前缀和
前缀和甚至能够解决二维数组中区间和的问题。
前缀和的一个总结见链接:
https://blog.csdn.net/weixin_43462819/article/details/100731522
另外还有使用前缀和的子数组的连续和:303:https://leetcode.com/problems/range-sum-query-immutable/

在这里插入图片描述

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        unordered_map<int, int> m;//first为前缀和(从第一个开始一直加到现在的),second为数目
        int sum = 0;
        int ret = 0;
        m[0] = 1;//这应该是自己检查的时候发现sum为k的时候出现问题然后添加上去的。含义是前缀和为0,至少有一种情况,就是什么都不包含
        
        for(int i = 0; i < nums.size(); ++i) {
            sum += nums[i];
            if(m.find(sum-k) != m.end())
                ret += m[sum-k];
            m[sum]++;
        }
        return ret;
    }
};

需要注意的就是说:我们迭代到其中一个数的时候,map当中已经包含了从零到它前面各个位置的前缀和。然后又会遍历所有位置,所以是对的。
在这里插入图片描述

class Solution {
public:
    int subarraysDivByK(vector<int>& A, int K) {
        unordered_map<int, int> m;//first为前缀和(从第一个加到现在的这个)除K的余数,如果为负数,加上K
        int sum = 0;
        int cnt = 0;
        m[0] = 1;
        
        for(int i = 0; i < A.size(); ++i) {
            sum += A[i];
            int temp = sum % K;
            if(temp < 0)
                temp += K;
            if(m.find(temp) != m.end())
                cnt += m[temp];
            m[temp]++;
        }
        return cnt;
    }
};

值得注意的是,余数可能为负数,这种情况下,需要加上K。也就是说,比如K为5,那么如果余数为-1,我们需要将它变为4。这样它产生的效果才是一样的。

这里的启发是:使用前缀和方法,存的不一定是前缀和,根据实际情况存下一些东西,但是应该都是根据前缀和计算出来的。比如这里的余数就是根据前缀和计算出来的。

posted @ 2019-08-16 14:58  于老师的父亲王老爷子  阅读(14)  评论(0编辑  收藏  举报