如果有一个数组arr = [1, 5, 8, 2, 13, 6],我们对其进行T次询问,每次询问[r, l](r, l均为数组arr的下标,在此数组中符合(0 <= r <= 5)),假设对其询问3次(T = 3),第一次询问[1,3],第二次询问[2,4],第三次询问[2,5],我们不难算出来,第一次询问的结果是5 + 8 + 2 = 15,第二次询问的结果是8 + 2 + 13 = 23,第三次询问的结果是8 + 2 + 13 + 6 = 29,当然,如果数组长度比较短的话当然可以这么做,如果当数组的长度比较长时,询问T次最坏情况下无非就是每次都询问[0, arr.length()]的区间和,其时间复杂度为O(N * T),这样的时间代价无非时非常高的,这时候我们不妨引入前缀和的概念:
我们不妨维护一个数组nums,使得nums当i > 0 时,nums[i] = nums[i - 1] + arr[i], i = 0 时,nums[0] = arr[0]; 此时我们再对arr数组进行处理,nums = [1, 6, 14, 16, 29, 35],此时的nums[i]就是arr中[0, i]的区间和, 好的,直接上公式,当l(区间的左边界) = 0时,arr[l, r] = nums[r], 当l > 0时,arr[l, r] = nums[r] – nums[l - 1],此时我们不妨将上面询问三次将公式里带入求证,当询问[1, 3]时,arr[1, 3] = nums[3] – nums[0] = 16 – 1 = 15, 当询问[2, 4]时,arr[2, 4] = nums[4] – nums[1] = 29 – 6 = 23,当询问[2, 5]时,arr[2, 5] = nums[5] = nums[1] = 35 – 6 = 29。看样子完全正确,这就是利用了前缀和,其时间复杂度为O(1),能极大的缩短我们的询问时间,提高我们的效率。
下面是代码块:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int i, t;
vector<int>arr = {1, 5, 8, 2, 13, 6};
vector<int>nums(6, 0);
//建立数组nums
for (i = 0; i < 6; i++) {
if (i == 0)
nums[i] = arr[i];
else
nums[i] = nums[i - 1] + arr[i];
}
cin >> t;
//对其进行t次询问
while (t--) {
int l, r;
cin >> l >> r;
cout << "区间[" << l <<"," << r << "]的前缀和为:";
if (l > 0)
cout << nums[r] - nums[l - 1] << endl;
else
cout << nums[r] << endl;
}
system("pause");
return 0;
}
运行结果: