算法使用技巧之-差分数组

差分数组是用于区间修改操作的辅助数据结构,它记录了原始数组相邻元素的差值。通过差分数组,可以高效地处理区间加减操作,并在力扣(LeetCode)等平台上的题目中得到应用,如航班预订统计问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

差分数组的定义

差分数组就是原始数组相邻元素的差。

定义如下,给定原始数组nums,则对应的差分数组min就是相邻元素之间的差,用公式表示为:

min[i] = \left\{\begin{matrix} nums[i]-nums[i-1] & i>0 \\ nums[i]&i==0 \end{matrix}\right.

数组定义的性质:

  • 原数组nums中的每一项num[i] 是差分数组min[i]的前缀和,用公式表示为nums[i] = \sum_{i=0}^{i} min[i]

差分数组可以维护多次对数组的一个区间加上一个数,并在最后询问某一位的数值或者多次询问某一位的数值。

举例:

序号01234
原数组nums249710
差分数组min225-23

其实差分数组是一个辅助数组,从侧面来表示给定某一数组的变化,一般用来对数组进行区间修改的操作。

比如上面的数组,我们需要进行以下操作:

  • 将区间[0,2]之间的数值加3
  • 将区间[1,3]之间的数值减5

第一个操作

序号01234
原数组nums2+3=54+3=79+3=12710
差分数组min2+3=52不变5不变-2-3=-53

第二个操作

序号01234
原数组nums2+3=54+3=7-5=29+3=12-5=77-5=210
差分数组min2+3=52-5=-35不变-2-3=-5不变3+5=8

这时我们就会发现这样一个规律,当对一个区间进行增减某个值的时候,他的差分数组对应的区间左端点的值会同步变化,而他的右端点的后一个值则会相反地变化。

差分数组的应用

差分数组的作用就是求多次进行区间修改后的数组。

注意:只能是区间元素同时增加或减少相同的数的情况才能用

因为我们的差分数组是由原始数组的相邻两项作差求出来的,即 nums[i]=nums[i]-nums[i-1];那么我们能不能反过来,求得一下修改过后的nums[i]呢?

直接反过来即得 nums[i]=nums[i-1]+min[i]

差分数组在力扣题目中的使用

LeetCode 1109. 航班预订统计

/**
 * @param {number[][]} bookings
 * @param {number} n
 * @return {number[]}
 */
var corpFlightBookings = function(bookings, n) {
    //航班预订初始值为0,对应的差分数组值也为0
    const nums = new Array(n).fill(0);
    for(const book of bookings){
        //差分数组左断点操作值
        nums[book[0]-1] += book[2];
        if(book[1] < n){
            //差分数组右端点反向操作
            nums[book[1]] -= book[2];
        }
    }
    for(let i=1;i<n;i++){
        //求前缀和
        nums[i] = nums[i] + nums[i-1];
    }
    return nums;
};

LeetCode1094. 拼车

/**
 * @param {number[][]} trips
 * @param {number} capacity
 * @return {boolean}
 */
var carPooling = function(trips, capacity) {
    const nums = new Array(1002).fill(0);
    let sum = 0;
    for(const trip of trips){
        nums[trip[1]] += trip[0];
        if(trip[2] < 1000){
            nums[trip[2]] -= trip[0];
        }
    }
    for(let i=0;i<nums.length;i++){
        sum += nums[i];
        if(sum > capacity){
            return false;
        }
    }
    return true;
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值