前缀和(C++)

算法的种类很多,虽然我目前掌握的不多,但是在我浅薄的认知里,我把算法分为两类。
一类是小算法,比如前缀和与快速幂这种,为什么说它们是小算法呢,因为,它们的用法比较单一,不算是一种庞大的思想,一般不能决定整个算法的走向,而是为降低程序时间复杂度的一个小操作,一种锦上添花的小装饰。
另一类是大算法,比如贪心和动态规划这种,这种算法直接关系到解决某个问题的全局思想,出现的形式多样,运用起来也比较灵活。
哈哈,废话不再多说,来解释一下前缀和吧~

定义

前缀和(Prefix sum)就是,对于一个给定数组a,它的前缀和数列是s[i]=(从a[0]+a[1]+…a[i])(其实是一种预处理的思想吧)

前缀和的最典型应用就是求数组某个子段的和

由于时间复杂度非常低,仅为O(1),所以得到了广泛的应用

一维前缀和定义

举个小栗子吧~
一个长度为n的数组a,求第l个元素到第r个元素的和

//by LMY
int a[50] = {0}, s[50] = {0}, i, l, r, n;
//a是原数组,s是前缀和数组
	cin >> n;
	cin >> l >> r;
	for (i = 1; i <= n; i++)
	{
		cin >> a[i];
		s[i] = s[i - 1] + a[i];
		//这一步是前缀和数组的构建
	}
	cout << s[r] - s[l - 1] << "\n";
	//求子数组的和
二维前缀和定义
//二维前缀和
//把s[0][i]和s[i][0]全部置为0
//s[i-1][j-1]加重复了,需减去
s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];

不要忘记对原始数组初始化哦,因为使用前缀和是往往是从a[1]开始的,要把a[0]初始化为0的鸭~

### 递推式前缀和算法C++ 实现方法 递推式前缀和算法是一种高效的预处理技术,用于快速计算数组中任意子区间的元素和。实现过程主要包括两个步骤:**构建前缀和数组**和**使用前缀和数组进行查询**。 #### 1. 构建前缀和数组 在构建阶段,需要定义一个与原数组大小相同的 `dp` 数组,其中 `dp[i]` 表示原数组中从索引 `1` 到 `i` 的所有元素之和(假设数组索引从 `1` 开始)。递推公式为: ```cpp dp[i] = dp[i - 1] + arr[i]; ``` 此公式表明,当前项的前缀和等于前一项的前缀和加上当前项的值。该过程的时间复杂度为 O(n),其中 n 是数组的长度[^2]。 #### 2. 使用前缀和数组进行区间求和查询 当需要查询数组中某个区间 `[left, right]` 的元素和时,可以通过以下公式快速计算: ```cpp sum = dp[right] - dp[left - 1]; ``` 该公式的原理是利用前缀和数组中 `dp[right]` 表示 `[1, right]` 区间的总和,减去 `dp[left - 1]` 表示 `[1, left - 1]` 区间的总和,最终结果即为 `[left, right]` 区间的总和[^3]。 #### 示例代码 以下是一个完整的 C++ 实现示例: ```cpp #include <iostream> #include <vector> using namespace std; int main() { // 原数组,索引从1开始 vector<int> arr = {0, 2, 4, 6, 8, 10}; // arr[0] 不使用 int n = arr.size() - 1; // 有效元素个数 // 创建并填充前缀和数组 vector<int> dp(n + 1, 0); // dp[0] 初始化为0 for (int i = 1; i <= n; ++i) { dp[i] = dp[i - 1] + arr[i]; // 递推公式 } // 查询 [2, 4] 区间的和 int left = 2; int right = 4; int sum = dp[right] - dp[left - 1]; cout << "Sum from index " << left << " to " << right << " is: " << sum << endl; return 0; } ``` 输出结果为: ``` Sum from index 2 to 4 is: 18 ``` #### 复杂度分析 - **时间复杂度**: - 构建前缀和数组:O(n) - 每次查询操作:O(1) - **空间复杂度**: - 额外空间 O(n),用于存储前缀和数组[^3]。 #### 注意事项 - 如果原数组的索引是从 `0` 开始,则可以相应调整递推公式和查询逻辑。 - 在实际应用中,可以根据需求选择是否将前缀和数组作为独立数组保存,或者直接修改原始数组(如果允许)以节省内存。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值