牛客题霸-数组求和统计
输入
[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=0rai−∑i=0l−1ai
因此先用一个数组a[i]保存区间[0, i]的和,这样再求连续区间的和就不用反复计算了。
接下来有推算:
∑
i
=
l
r
a
i
=
b
l
+
b
r
\sum_{i=l}^r a_i = b_l+b_r
i=l∑rai=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=0∑rai−i=0∑l−1ai=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=0∑l−1ai=i=0∑rai−br..........(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=0k−1ai,方法是先存
b
k
+
∑
i
=
0
k
−
1
a
i
b_k+\sum_{i=0}^{k-1} a_i
bk+∑i=0k−1ai,再统计
∑
i
=
0
k
a
i
−
b
k
\sum_{i=0}^k a_i -b_k
∑i=0kai−bk。理由是,在满足(1)式的情况下,区间left端总是不大于right端的,当我们需要在map中找
∑
i
=
0
r
a
i
−
b
r
\sum_{i=0}^r a_i -b_r
∑i=0rai−br的时候,
b
l
+
∑
i
=
0
l
−
1
a
i
b_l+\sum_{i=0}^{l-1} a_i
bl+∑i=0l−1ai总是统计好了。
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)