差分数组的练习

来源:【算法小课堂】差分数组
在这里插入图片描述

1109. 航班预订统计

1109. 航班预订统计
根据题意,需要返回一个数组,其中每个元素是当前航班的预定座位的个数。
在预定记录 bookings 中,每一个预订记录实际上代表了一个区间的增量,因此结果就可以从这些增量叠加得到答案。因此,我们可以使用差分解决本题。

差分数组的性质是,当我们希望对原数组的某一个区间 [l,r] 施加一个增量 inc 时,差分数组 d 对应的改变是:d[l] 增加 incd[r+1] 减少 inc。其中,d[r+1] 减少 inc 的原因是,d 中的后续区间元素需要消除 inc 的影响,否则在从左到右累加 d 中的元素时 r+1 以及后续的元素都会再加上 inc,导致出错。

注意本题中航班的编号从 1 到 n 的,因此我们需要相应的调整数组下标对应关系,对于预定记录 booking=[l,r,inc],我们需要让 d[l−1] += incd[r] -= inc。特别地,当 r = n 时,我们无需修改 d[r],因为这个位置溢出了下标范围。

class Solution {
public:
    vector<int> corpFlightBookings(vector<vector<int>>& bookings, int n) {
        vector<int> d (n);
        for (auto& b : bookings) {
            d[b[0]-1] += b[2];
            if (b[1] < n) d[b[1]] -= b[2];
        }
        for (int i=1; i < n; i++)  
        	d[i] += d[i-1];
        return d;
    }
};
/**
 * @param {number[][]} bookings
 * @param {number} n
 * @return {number[]}
 */
var corpFlightBookings = function(bookings, n) {
    const diff = Array(n).fill(0);
    for ([first, last, num] of bookings) {
        diff[first-1] += num;
        if (last < n) diff[last] -= num; 
    }
    for (let i=1; i < n; i++) 
    	diff[i] += diff[i-1];
    return diff;
};

2381. 字母移位 II

2381. 字母移位 II
根据题意,将小写英文字母组成的字符串 s 里的字符都进行移位运算,最终返回移位后最终字符串。在 shifts 中,每一个元素实际上代表了一个区间内字符的位移情况,因此结果就可以从这些位移叠加得到答案。因此,我们可以使用差分解决本题。
用差分数组 diff 表示一段区间上的移位,即在 s t a r t i start_i starti 变化量增加了 x x x,在 e n d i + 1 end_i+1 endi+1 变化量减少了 x x x
其中 x x x 是根据 d i r e c t i o n i direction_i directioni 求得:
d i r e c t i o n i = 1 direction_i=1 directioni=1 时,diff[start_i] += 1diff[end_i+1] -= 1
d i r e c t i o n i = 0 direction_i=0 directioni=0 时,diff[start_i] -= 1diff[end_i+1] += 1

最后,从小到大遍历 diff,累加变化量为 d d d,这样对于第 i i i 个字符,其移位值就是 d d d

/**
 * @param {string} s
 * @param {number[][]} shifts
 * @return {string}
 */
var shiftingLetters = function(s, shifts) {
    const n = s.length;
    const diff = Array(n+1).fill(0);
    for (x of shifts) {
        diff[x[0]] = x[2] == 1 ? diff[x[0]] + 1 : diff[x[0]] - 1;
        diff[x[1]+1] = x[2] == 1 ? diff[x[1]+1] - 1 : diff[x[1]+1] + 1;
    }
    let d = 0;
    let ans = '';
    for (let i=0; i < n; i++) {
        d += diff[i];
        let newCharCode = (s.charCodeAt(i) - 'a'.charCodeAt(0) + d) % 26;  // 计算新的字符
        if (newCharCode < 0) newCharCode += 26;  // 防止负数出现
        ans += String.fromCharCode(newCharCode + 'a'.charCodeAt(0));  // 拼接新字符
    }
    return ans;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值