前缀和(一)

前缀和(一)

写在前面

前缀和极其有用,用来优化算法复杂度,有的时候甚至可以优化掉次方级别的复杂度(因为很多时候我们使用循环就意味着会做很多的重复计算),用一句话总结其本质思想就是,想办法把我们之前算出的能够重复使用的数据存下来,用的时候从里面拿出来,当然存的过程就是耗费空间 的过程,所以我觉得这种思想也算是一种空间换取时间吧!

其实也就是容斥原理的运用!(附上百度百科容斥原理:在计数时,必须注意没有重复,没有遗漏。为了使重叠部分不被重复计算,人们研究出一种新的计数方法,这种方法的基本思想是:先不考虑重叠的情况,把包含于某内容中的所有对象的数目先计算出来,然后再把计数时重复计算的数目排斥出去,使得计算的结果既无遗漏又无重复,这种计数的方法称为容斥原理)

前缀和

顾名思义,前缀和就是前面 i 个数的总和。

应用场景:给出一串长度为n的数列a1,a2,a3…an,再给出m个询问,每次询问给出L,R两个数,要求给出区间[L,R]里的数的和,如果对于这m次询问,我们每一次都遍历一次,再计算出答案,固然没错,但是数据量大的时候就又可能超时,这时候我们就引入了前缀和的方法来降低时间复杂度。

原理:先计算出前面 i 个数的总和

a[0]=0;
 
for(int i=1;i<=n;i++)a[i]+=a[i-1];

然后每一次就计算a[R]-a[L-1]即可,原理很好理解。

栗子:

数列:【1,2,3,4,5,6,7,8, 9】

1的前缀和:1 = 1
2的前缀和:1+2 = 3
3的前缀和:1+2+3 = 6
4的前缀和:1+2+3+4 = 10
5的前缀和:1+2+3+4+5 = 15
6的前缀和:1+2+3+4+5+6 = 21
7的前缀和:1+2+3+4+5+6+7 = 28
8的前缀和:1+2+3+4+5+6+7+8 = 36
9的前缀和:1+2+3+4+5+6+7+8+9 = 45

求和如果按一般的两层for循环来写:就是

for (int i = 1; i <= n; ++i) 
	for (int j = 1; j <= i; ++j) //从第一个到自己
		sum[i] += arr[i];

复杂度是N^2的,我们用前缀和的思想来写,可以写出O(N)的算法:

for (int i = 1; i <= n; ++i) {
	sum[i] = sum[i - 1] +a[i];
}

也就容易得出求[l,r]的区间和的公式:sum[r]-sum[l-1]。

当然我们实际遇到的相关问题不会这么简单了。

二维数组前缀和

与前面同理,画图理解之后容易得到

S[ i , j ] = S[ i- 1 ,j ] + S[i , j-1 ] - S[i - 1 , j-1 ] + A[ i , j ]

假如我想求a24的前缀和,我得先加上a13的前缀和,再加上a23的前缀和,然后这个时候我们发现实际上a13这个部分我们加了两遍,所以我们需要再减去一遍a13.

就介绍到这里,我会在之后的博文里列举一些题目来感受一下它的魅力!!!


今日推歌

----《凄美地》

嘿 等我找到你
试探你眼睛
心无旁骛地 相拥
那是我 仅有的温柔也是我爱你的原因
在这凄美地
在这之前 别说再见
我已再经不起离别
在这之前 别说再见
我已经开始了想念
在这之前 别说再见
请帮我停住这时间

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星回昭以烂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值