差分数组使用场景:

  • 频繁对数组的一段区间进行增加或者减去同一个值,快速对区间做加减法
  • 询问区间和问题

差分数组定义:

存在数组A[n],定义差分数组d[n]满足:

性质:

从l到r对原数组都加上k:

for(int i=l,i<=r;i++){
      A[n]+=k;
}

但对于差分数组的变化是:

d[l]+=k;
d[r+1]-=k;

此时我们仍然可以通过差分数组,通过前缀和来恢复数组A。
由上述可以发现差分数组可以快速对区间做加减法,由此这个可以配合前缀和数组以及树状数组来完成一些操作;
以前缀和数组来举例,原数组中的元素i+K,那么前缀和数组从i开始往后都要+i,通过构建前缀和数组的差分数组,只需要改动一个元素即可。

例题:

美团校招题:路由器
https://www.nowcoder.com/questionTerminal/220361995bb64de08dc47c646ee111ab

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int k = scanner.nextInt();
        int cnt = 0;
        int[] router = new int[n]; //差分数组
        for(int i = 0; i < n; i++){
            int signal = scanner.nextInt(); //当前路由器的信号
            int start = Math.max(i - signal, 0);//router[0]=router[0]-router[-1],router[-1]=0没有具体表示出来;
            router[start]++;
            if(signal + i + 1 < n){
                router[signal + i + 1]--;
            }
        }
        //通过前缀和 恢复原数组
        int sum = 0;
        for(int i = 0; i < router.length; i++){
            sum += router[i];
            if(sum >= k){
                cnt++;
            }
        }
        System.out.println(cnt);
    }
}