【la】差分数组

差分数组概述

1. 应用场景

频繁对原始数组的某个区间的元素进⾏增减。
给你输⼊⼀个数组 nums,给nums[i…j] 加上 val。

2. 差分数组使用方法
2.1 构造差分数组

对 nums 数组构造⼀个 diff 差分数组,diff[ i ] = nums[ i ] - nums[ i - 1 ]
在这里插入图片描述


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];
}

2.2 由差分数组反推原始数组

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];
}

2.3 快速进⾏区间增减的操作

对区间 nums[i…j] 的元素全部加 val
(减 val 就是加 -val)
只需要让 diff [ i ] + = valdiff [ j + i ] - = val

2.4 将差分数组抽象成一个类Difference,包含 increment ⽅法和 result ⽅法:

    // 差分数组⼯具类
    class Difference {
        // 差分数组
        private int[] diff;
        /* 输⼊⼀个初始数组,区间操作将在这个数组上进⾏ */
        public Difference(int[] nums) {
            assert nums.length > 0;
            /**
             * assert <boolean表达式>
             *  如果<boolean表达式>为true,则程序继续执行。
             *  如果为false,则程序抛出AssertionError,并终止执行
             */
            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;
        }
    }

这⾥注意⼀下 increment ⽅法中的 if 语句:


public void increment(int start,int end,int val){
     diff[start] += val;
     if (end + 1 < diff.length)
        diff[end+1] -= val;
     }
  }

当 j+1 >= diff.length 时,说明是对 nums[i] 及以后的整个数组都进⾏修改,那么就不需要再给 diff 数组减 val 了。
在这里插入图片描述

1109. 航班预订统计


这里有 n 个航班,它们分别从 1 到 n 进行编号。

有一份航班预订表 bookings ,表中第 i 条预订记录 bookings[i] = [firsti, lasti, seatsi] 
意味着在从 firsti 到 lasti (包含 firsti 和 lasti )的 每个航班 上预订了 seatsi 个座位。

请你返回一个长度为 n 的数组 answer,里面的元素是每个航班预定的座位总数。

 
示例 1:

输入:bookings = [[1,2,10],[2,3,20],[2,5,25]], n = 5
输出:[10,55,45,25,25]
解释:
航班编号        1   2   3   4   5
预订记录 110  10
预订记录 220  20
预订记录 325  25  25  25
总座位数:      10  55  45  25  25
因此,answer = [10,55,45,25,25]

示例 2:

输入:bookings = [[1,2,10],[2,2,15]], n = 2
输出:[10,25]
解释:
航班编号        1   2
预订记录 110  10
预订记录 215
总座位数:      10  25
因此,answer = [10,25]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/corporate-flight-bookings
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
    public int[] corpFlightBookings(int[][] bookings, int n) {
        int r = bookings.length;
        int[] diff = new int[n+1]; // 都是从 1 开始存放数字的
        int[] res = new int[n+1]; // 有 n 个航班,res[i] 存放第i个航班预订的座位数
        for (int i = 0;i < r;i++){
            int left = bookings[i][0];
            int right = bookings[i][1];
            int val = bookings[i][2];

            diff[left] += val;
            if (right+1 <= n){
                diff[right+1] -= val;
            }

        }
        // 由差分数组求原数组  diff[i] = nums[i] - nums[i-1]
        res[1] = diff[1];
        for (int i = 2;i <= n;i++){
            res[i] = diff[i] + res[i-1];
        }
        return Arrays.copyOfRange(res,1,res.length);
    }
}

1094. 拼车


假设你是一位顺风车司机,车上最初有 capacity 个空座位可以用来载客。
由于道路的限制,车 只能 向一个方向行驶(也就是说,不允许掉头或改变方向,你可以将其想象为一个向量)。

这儿有一份乘客行程计划表 trips[][],其中 trips[i] =
 [num_passengers, start_location, end_location] 包含了第 i 组乘客的行程信息:
    必须接送的乘客数量;
    乘客的上车地点;
    以及乘客的下车地点。

这些给出的地点位置是从你的 初始 出发位置向前行驶到这些地点所需的距离(它们一定在你的行驶方向上)。

请你根据给出的行程计划表和车子的座位数,来判断你的车是否可以顺利完成接送所有乘客的任务
(当且仅当你可以在所有给定的行程中接送所有乘客时,返回 true,否则请返回 false)。

 

示例 1:

输入:trips = [[2,1,5],[3,3,7]], capacity = 4
输出:false

示例 2:

输入:trips = [[2,1,5],[3,3,7]], capacity = 5
输出:true

示例 3:

输入:trips = [[2,1,5],[3,5,7]], capacity = 3
输出:true

示例 4:

输入:trips = [[3,2,7],[3,7,9],[8,3,9]], capacity = 11
输出:true

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/car-pooling
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


class Solution {
public boolean carPooling(int[][] trips, int capacity) {
        int[] res = new int[1010];
        // res 是每一站的乘客数量,只要每一站乘客数量都 <= capacity,就返回 true
        int[] diff = new int[1010]; 
        // 差分数组
        int m = trips.length;
        for (int i = 0;i < m;i++){
            // 给res数组 从上车地 到 下车地-1 加上乘客数量
            // diff[left] += val, diff[right+1] += val
            int val = trips[i][0];
            int left = trips[i][1];
            int right = trips[i][2]-1;
            // 第 trips[i][2] 站乘客已经下车,加到 trips[i][2]-1 就可以了

            diff[left] += val;
            diff[right+1] -= val;
        }
        // 求出原数组
        res[0] = diff[0];
        for (int i = 1;i<diff.length;i++){
            // diff[i] = nums[i] - nums[i-1]
            res[i] = diff[i] + res[i-1];
        }

        for(int i = 0;i < res.length;i++){
            if (res[i] > capacity){
                return false;
            }
        }
        return true;
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值