算法笔记Day5——经典数组技巧:差分数组

关键字:区间,加和

介绍

前缀和实际上就是求积分(离散),差分就是求导,它们之间互为逆运算。

前缀和主要适用于原数组不变,频繁查询某个区间的累加和。

差分适用于频繁对某区间的元素进行增减(原数组要变),如果是原数组来操作的话,每次区间加减都需要O(N)的时间复杂度,但是差分数组只需要O(1)的时间复杂度,很多次加减操作的话,这个差距就很大了,差分数组回到原数组需要O(N)的时间复杂度,但是只需要一次。

解题范式

 1. 创建diff数组,对每一次加减都对diff进行运算(

for ( auto once : all ){

diff[start] += val; 

if(!越界) diff[end] -= val.

}

 2. 还原数组,for(int i  =1; i< n; i++){    diff[ i ] += diff[ i - 1];    }

练习题

例题1:航班预订统计

分析

差分和暴力的区别在于,由于差分的性质每次订票是O(1)复杂度,而暴力是O(N),差分将O(N)的操作提到最后去了,只有一次O(N)的操作,所以当订票(增减数组很多的时候),使用差分数组可以得到很高的效率提升。

代码

class Solution {
public:
    vector<int> corpFlightBookings(vector<vector<int>>& bookings, int n) {
        vector<int> diff(n);
        for(auto booking : bookings){
            diff[booking[0] - 1] += booking[2];
            if(booking[1] < n){
                diff[booking[1]] -= booking[2];
            }
        }
        for(int i = 1; i< n; i++){
            diff[i] += diff[i-1];
        }
        return diff;
    }
};

总结

i)区间加和的模板,差分数组:左区间直接加,右区间不越界需要减去(如果越界说明后面所有都加不需要减了)

ii)差分数组可以直接累加得到原数组,不需要额外开一个空间。

例题2:拼车

分析:这里减法的地方不需要判断是否越界是因为数组开的1001序号能够到1000.

代码

#define MAXMILE 1001
class Solution {
public:
    bool carPooling(vector<vector<int>>& trips, int capacity) {
        vector<int> diff(MAXMILE);
        for(auto trip : trips){
            if(trip[0] > capacity){
                return false;
            }
            diff[trip[1]] += trip[0];
            diff[trip[2]] -= trip[0]; 
        }
        for(int i = 1; i< MAXMILE; i++){
                diff[i] += diff[i-1];
                if(diff[i] > capacity){
                    return false;
                }
            }
        return true;
    }
};

总结:无

  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值