差分数组+LeetCode1109

差分数组定义性质及用途

1.定义

对于一个长度大小为n的数组arr[n] 我们可以建立他的差分数组f[n]。其中f[i] = arr[i] - arr[i-1]。 
例如 f[2] = arr[2] - arr[1]。

2.性质

(1) 可通过差分数组计算arr[i]的值:
	arr[i] = f[i] + f[i-1] + ... + f[0]  或 arr[i] = f[i] + arr[i-1]
(2) 计算数组每一项的前缀和:
	![在这里插入图片描述](https://www.icode9.com/i/ll/?i=2021051111293737.png#pic_center)
	这里简单解释一下: 如果要求sum2 则sum2 = arr[0] + arr[1] + arr[2] 
	而每个arr[i] = f[i] + f[i-1] + ... + f[0]  故 sum2的求解中 f[0]出现3次 f[1]出现2次 f[2] 1次
	故sum[2] = 3 * f[0] + 2 * f[1] + 1 * f[2]

3.用途

(1) 区间快速加减操作:
	假如现在对数列中区间[L,R]上的数加上x,我们通过性质(1)知道,第一个受影响的差分数组中的元素为f[L],
即令f[L]+=x,那么后面数列元素在计算过程中都会加上x;最后一个受影响的差分数组中的元素为f[R],
所以令f[R+1]-=x,即可保证不会影响到R以后数列元素的计算。这样我们不必对区间内每一个数进行处理,
只需处理两个差分后的数即可。
(2) 询问区间和
	求区间[l, r]的和即为 sum[R] - sum[L-1]  

例题 LeetCode1109

差分数组+LeetCode1109

import java.util.Arrays;

public class Solution {
    
    // 原数组
    private int[] arr;
    // 差分数组
    private int[] f;
    
    public int[] corpFlightBookings(int[][] bookings, int n) {
        arr = new int[n];
        f = new int[n];
        int l = 0;
        int r = 0;
        int seats = 0;
        for (int i = 0; i < bookings.length; i++) {

            // 注意我们维护的数组下标从0开始 所以要减去偏移量1
            l = bookings[i][0] - 1;
            r = bookings[i][1] - 1;
            seats = bookings[i][2];
            // 差分数组f[l, r] 中 f[l]要加上座位数
            f[l] += seats;
            // f[r+1]如果超过数组长度 也continue
            if (r + 1 >= n)
                continue;
            // 差分数组右边界下一个数值要减去 增加的座位数
            f[r+1] -= seats;
        }
        // 根据差分数组求出最终结果
        arr[0] = f[0];
        for (int i = 1; i < n; i++) {
            arr[i] = f[i] + arr[i-1];
        }
        return arr;
    }

    public static void main(String[] args) {
        int[][] commend = {{1,2,10},{2,3,20},{2,5,25}};
        int[] res = new Solution().corpFlightBookings(commend, 5);
        for (int num : res)
            System.out.print(num + " ");
    }
}

上一篇:2021-07-08


下一篇:操作系统习题1