(刷题笔记)差分数组介绍和应用

差分数组介绍和应用

差分数组的主要适用场景是频繁对原始数组的某个区间的元素进行增减

如:输入一个数组 nums,然后又要求给区间 nums[2..6] 全部加 1,再给 nums[3..9] 全部减 3,再给 nums[0..4] 全部加 2…

如果每次都遍历数组,效率低下,可以考虑构建差分数组

核心代码:

int[] diff = new int[nums.length];
// 构造差分数组
diff[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
    diff[i] = nums[i] - nums[i - 1];
}

diff 差分数组可以反推出原始数组 nums

int[] res = new int[diff.length];
// 根据差分数组构造结果数组
res[0] = diff[0];
for (int i = 1; i < diff.length; i++) {
    res[i] = res[i - 1] + diff[i];
}

这样构造差分数组 diff,就可以快速进行区间增减的操作,如果你想对区间 nums[i..j] 的元素全部加 3,那么只需要让 diff[i] += 3,然后再让 diff[j+1] -= 3 即可(注意是j+1)

// 差分数组工具类
class Difference {
    private int[] diff;
    /* 输入一个初始数组,区间操作将在这个数组上进行 */
    public Difference(int[] nums) {
        assert nums.length > 0;
        diff = new int[nums.length];
        // 根据初始数组构造差分数组
        diff[0] = nums[0];
        for (int i = 1; i < nums.length; i++) {
            diff[i] = nums[i] - nums[i - 1];
        }
    }
    /* 给闭区间 [i,j] 增加 val(可以是负数)*/
    public void increment(int i, int j, int val) {
        diff[i] += val;
        if (j + 1 < diff.length) {
            diff[j + 1] -= val;
        }
    }
    /* 返回结果数组 */
    public int[] result() {
        int[] res = new int[diff.length];
        // 根据差分数组构造结果数组
        res[0] = diff[0];
        for (int i = 1; i < diff.length; i++) {
            res[i] = res[i - 1] + diff[i];
        }
        return res;
    }
}

差分数组相关题型

LeetCode1094 拼车

    public boolean carPooling(int[][] trips, int capacity) {
         // 最大值为1000
        int[] diff = new int[1000];
        for (int[] trip : trips){
            int num = trip[0];
            int start = trip[1];
            // trip[2]下车,所以上一时刻还有人
            int end = trip[2]-1;
            diff[start] += num;
            if (end+1 < diff.length)
                diff[end+1] -= num;
        }
        int[] res = new int[diff.length];
        res[0] = diff[0];
        for (int i = 1; i < res.length; i++) {
            res[i] = diff[i] + res[i-1];
        }
        for (int i = 0; i < res.length; i++) {
            if (capacity<res[i])
                return false;
        }
        return true;
    }

LeetCode1109. 航班预订统计

    public int[] corpFlightBookings(int[][] bookings, int n) {
        int[] answer = new int[n];
        int[] diff = new int[n];
        for (int[] booking : bookings){
            // 因为n从1开始编号,所以下边统减一
            int first = booking[0]-1;
            int last = booking[1]-1;
            int seat = booking[2];
            diff[first] += seat;
            if(last + 1 < n)
                diff[last+1] -= seat;
        }
        answer[0] = diff[0];
        for (int i = 1; i < n; i++) {
            answer[i] = diff[i] + answer[i-1];
        }
        return answer;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值