牛客题霸-数组求和统计

牛客题霸-数组求和统计

在这里插入图片描述

输入
[1,2,3,4],[2,1,4,5]

输出
4

说明
满足条件的数对有(0, 1), (0, 2), (1, 1), (1, 2)(0,1),(0,2),(1,1),(1,2)

要求一个数组中连续区间的和,很自然地想到 :
∑ i = l r a i = ∑ i = 0 r a i − ∑ i = 0 l − 1 a i \sum_{i=l}^r a_i =\sum_{i=0}^r a_i - \sum_{i=0}^{l-1} a_i i=lrai=i=0raii=0l1ai
因此先用一个数组a[i]保存区间[0, i]的和,这样再求连续区间的和就不用反复计算了。
接下来有推算:
∑ i = l r a i = b l + b r \sum_{i=l}^r a_i = b_l+b_r i=lrai=bl+br
∑ i = 0 r a i − ∑ i = 0 l − 1 a i = b l + b r \sum_{i=0}^r a_i - \sum_{i=0}^{l-1} a_i= b_l+b_r i=0raii=0l1ai=bl+br
b l + ∑ i = 0 l − 1 a i = ∑ i = 0 r a i − b r . . . . . . . . . . ( 1 ) b_l+\sum_{i=0}^{l-1} a_i =\sum_{i=0}^r a_i -b_r ..........(1) bl+i=0l1ai=i=0raibr..........(1)
由以上推算可以看出,只需判断(1)式即可,并且(1)有一个特点:和左右边界相关的式子各在一边,可等价于找(1)左右两边相等的情况的次数。
因此可以采取一个策略,在遍历到第k次时,统计第k次以及之前出现过的 b k + ∑ i = 0 k − 1 a i b_k+\sum_{i=0}^{k-1} a_i bk+i=0k1ai,方法是先存 b k + ∑ i = 0 k − 1 a i b_k+\sum_{i=0}^{k-1} a_i bk+i=0k1ai,再统计 ∑ i = 0 k a i − b k \sum_{i=0}^k a_i -b_k i=0kaibk。理由是,在满足(1)式的情况下,区间left端总是不大于right端的,当我们需要在map中找 ∑ i = 0 r a i − b r \sum_{i=0}^r a_i -b_r i=0raibr的时候, b l + ∑ i = 0 l − 1 a i b_l+\sum_{i=0}^{l-1} a_i bl+i=0l1ai总是统计好了。

class Solution {
public:
    int countLR(vector<int>& a, vector<int>& b) {
    	//a中0~i的区间和
        for(int i = 1; i < a.size(); i++)
            a[i] += a[i-1];
        
        int ans = 0;  
        map<int, int> count;
        count[0] = b[0];
        for(int i = 1; i < b.size(); i++) {
            count[b[i]+a[i-1]]++;
            ans += count[a[i]-b[i]];
        }
        return ans;
    }
};

复杂度为O(n)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值