前缀和
什么是前缀和?
前缀和其实就是前几项数组中前N项的和,当然这个概念并不仅限于数组,定义可以非常广泛,可以拿一维数组举例。
下标 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
数组A | 2 | 1 | 7 | 9 | 10 |
数组S | 2 | 3 | 10 | 19 | 29 |
我们的目标数组为A数组,S数组为A数组的前缀和数组。其基本概念就是S【i】的值即为数组A中的A【1】~A【i】的和。
公式就为S[i] = s[i-1]+a[i]
那么我们看一个简单的应用
前缀和例题(来自AcWing)
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int n ,m;
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
int arr[] = new int[n+10];
int sur[] = new int[n+10];
sur [0] = 0;
for (int i = 1; i <= n;i) arr[i] = sc.nextInt();//输入目标数组
for (int j = 1; j <= n;j) sur[j] = sur[j-1]+arr[j];//构建目标数组的前缀和
while (m– > 0) {
int l,r,res;
l = sc.nextInt();
r =sc.nextInt();
res = sur[r] - sur[l-1];}
System.out.println(res);
在这道题中使用前缀和的方法就可以避免暴力算法而造成的超时影响,可以降低其时间复杂度。可能在更有难度的算法前缀和会是其中的一种优化的方法。
差分
作为一名初学算法的人来讲,之前竟然没有听说过差分的概念。
那么差分是什么呢?
其实和前缀和可以对应的来看,前缀和构建目标数组的前缀和数组
差分是把目标数组当成前缀和数组,来构建其原数组
下标 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
目标数组A | 4 | 7 | 9 | 13 | 15 |
差分数组B | 4 | 3 | 2 | 4 | 2 |
由上述图表可以看出,我们的目标数组A变成了B数组的前缀和数组。
差分数组可以用来干什么呢?
我们可以利用到前缀和数组的性质。我们假设要对数组中下标区间为[L,R]之间的数组元素全部加上C
那么如果用暴力的做法即对目标数组[L,R]区间循环加C,其时间复杂度为O(n)
如果用差分的数组来思考,由于A数组为B数组的前缀和。我们要将A数组的[L,R]区间都加上C。便可以对B[L]加C,对B[R+1]减C
因为当B[L]加C,A又是B数组的前缀和,即在A[L]之后的元素就会全部加上C
而在B[R+1]减去C,便消除了A[R]之后加C的影响,便完成了对A[L,R]的统一操作。
我们如何去构建差分数组呢?
1.利用前缀和 B[i] = A[i] - A[i-1]
2.我们可以把A数组的初值全部变成0,即B数组一开始便成为了A数组的差分数组,那么对于每一个A[i]来说,我们相当于在[i,i]区间加上A[i]的一个操作,对差分数组来说则是
B[i] = b[i]+c,B[i+1] = B[i+1]-c
mport java.util.Scanner;
public class Main {
public static void main(String[] args) {
int n,m;
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
int arr[] = new int[100010];
int brr[] = new int[100010];
for (int i = 1;i <= n;i++) arr[i] = sc.nextInt();//初始化目标数组
for (int i = 1;i <= n;i++) brr[i] = arr[i]-arr[i-1];//构建差分数组
while (m-- > 0) {
int l,r,c;
l = sc.nextInt();
r = sc.nextInt();
c = sc.nextInt();
brr[l] += c;
brr[r+1] -= c;
}
for (int i = 1;i <= n;i++) arr[i] = arr[i-1]+brr[i];//用差分数组重新构建目标数组
for (int i = 1; i <= n;i++) System.out.print(arr[i]+"");
}
}
完成!