前缀和与差分是计算机科学中常用的算法技术,它们主要用于高效地处理区间求和和区间修改的问题。这两者可视作互逆的操作。
一、前缀和
前缀和是一个序列的前n项和的集合,通常用于快速计算某个区间的和。我们设定数组a[]
为原始数组,定义一个前缀和数组s[]
,其中s[i]
表示a[1]
到a[i]
的和。
1. 前缀和的计算
前缀和的计算公式如下:
- 初始化:
s[0] = 0
- 推递公式:
s[i] = s[i-1] + a[i]
通过上述方法,我们可以在O(n)的时间复杂度内构建前缀和数组。对于任意的区间 [l, r]
,可以快速计算出其和,公式为:
sum(l, r) = s[r] - s[l-1]
这样就将区间求和的时间复杂度降到了O(1)
2.前缀和的代码示例
import java.util.Scanner;
public class PrefixSum {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 输入数组的大小
int n = sc.nextInt();
int[] arr = new int[n + 1]; // 原始数组,1-indexed
int[] prefixSum = new int[n + 1]; // 前缀和数组,1-indexed
// 填充原始数组
for (int i = 1; i <= n; i++) {
arr[i] = sc.nextInt();
}
// 计算前缀和
for (int i = 1; i <= n; i++) {
prefixSum[i] = prefixSum[i - 1] + arr[i]; // 前缀和的递推
}
// 输入需要查询的区间
int l = sc.nextInt();
int r = sc.nextInt();
// 使用前缀和计算区间和
int sum = prefixSum[r] - prefixSum[l - 1]; // 区间和公式
System.out.println("区间和:" + sum);
}
}
3.代码解析
在代码中,用户首先输入数组的大小 n
和元素。
随后,生成前缀和数组 prefixSum[]
。通过用户输入的查询区间 [l, r]
,使用公式 sum = prefixSum[r] - prefixSum[l - 1]
快速计算得出该区间内的和。
这种方式将单次查询的时间复杂度降低到 O(1),提高了整体效率。
二、差分
差分是前缀和的逆运算,主要用于快速更新区间。它允许我们在常数时间内对数组的区间进行加减操作。
1. 差分的概念
设数组 b[]
为差分数组,那么原数组 a[]
和差分数组之间的关系可以用以下公式表示:
a[i] = b[1] + b[2] + ... + b[i]
差分数组的构造也很简单:
b[1] = a[1]
b[i] = a[i] - a[i-1]
(对于 i > 1)
区间更新
对区间 [L, R]
增加一个常数 C
,可以通过以下两步在差分数组中实现:
b[L] += C
b[R + 1] -= C
这种操作的时间复杂度为O(1)。求出更新后的原数组 a[]
只需对差分数组进行前缀和计算即可
2.差分的代码示例
import java.util.Scanner;
public class DifferenceArray {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 输入数组的大小
int n = sc.nextInt();
int[] arr = new int[n + 1]; // 原始数组,1-indexed
int[] diff = new int[n + 2]; // 差分数组,1-indexed,额外加一以处理边界
// 填充原始数组
for (int i = 1; i <= n; i++) {
arr[i] = sc.nextInt();
}
// 构造差分数组
diff[1] = arr[1]; // 第一个元素
for (int i = 2; i <= n; i++) {
diff[i] = arr[i] - arr[i - 1]; // 差分公式
}
// 更新区间 [L, R] 加上 C
int L = sc.nextInt();
int R = sc.nextInt();
int C = sc.nextInt();
diff[L] += C; // 开始位置增加 C
diff[R + 1] -= C; // 结束位置后一个位置减少 C
// 将差分数组转化回原始数组
for (int i = 1; i <= n; i++) {
arr[i] = arr[i - 1] + diff[i]; // 恢复原数组
System.out.print(arr[i] + " "); // 输出更新后的数组
}
}
}
3.代码解析
在代码中,用户输入原始数组的元素,通过差分计算每个元素与前一个元素之间的差值。
通过用户输入的区间 [L, R]
,在差分数组中进行更新,分别在 diff[L]
和 diff[R + 1]
进行加减操作。
最后,通过对差分数组进行前缀和计算,恢复更新后的原数组。
总结
了解前缀和与差分,不仅能有效提高区间和查询的效率,还能快速处理区间更新。掌握这些算法,可以帮助我们解决许多实际编程挑战,使我们在面对大数据时更加得心应手。