算法分析与设计-----前缀和 差分

前缀和

什么是前缀和?
前缀和其实就是前几项数组中前N项的和,当然这个概念并不仅限于数组,定义可以非常广泛,可以拿一维数组举例。

下标12345
数组A217910
数组S23101929

我们的目标数组为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);

在这道题中使用前缀和的方法就可以避免暴力算法而造成的超时影响,可以降低其时间复杂度。可能在更有难度的算法前缀和会是其中的一种优化的方法。

差分

作为一名初学算法的人来讲,之前竟然没有听说过差分的概念。
那么差分是什么呢?
其实和前缀和可以对应的来看,前缀和构建目标数组的前缀和数组
差分是把目标数组当成前缀和数组,来构建其原数组

下标12345
目标数组A4791315
差分数组B43242

由上述图表可以看出,我们的目标数组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

一个例子(来自于AcWing)

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]+"");
    }
}

完成!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值