【蓝桥杯 | 备赛秘籍】真题解析之差分数组—一维、二维差分一套拿下,附蓝桥杯真题和代码实战!

在这里插入图片描述

🤵‍♂️ 个人主页: @AI_magician
📡主页地址: 作者简介:CSDN内容合伙人,全栈领域优质创作者。
👨‍💻景愿:旨在于能和更多的热爱计算机的伙伴一起成长!!🐱‍🏍

在这里插入图片描述


差分和前缀和其实是互逆的,为什么呢🙌,我们看到最后就会明白

差分数组

差分和前缀和其实是互逆的,一维差分我们可以知道, a[i] 是 b[1]…b[i] 的前缀和,如果我们要对区间 [l , r] 中的数都加上一个数c的话只需要让 b[l] += c 并且 b[r + 1] -= c 即可,这样用差分数组构建新数组时,区间 [l , r] 中的数都会在原基础上加上c。

一维差分
LeetCode 力扣 难度
1094. Car Pooling 1094. 拼车 🟠
蓝桥杯 重新排序 蓝桥杯 棋盘

差分数组的主要适用场景是频繁对原始数组的某个区间的元素进行增减。(核心思想便是提前计算好差分数组,通过差分数组与原数组之前的等式关系,从而只需要一次操作便可以对某个区间的元素进行增减)

算法技巧「差分数组」,类似前缀和技巧构造的 preSum 数组,对 nums 数组构造一个 diff 差分数组

对区间 nums[i..j] 的元素全部加 3,让 diff[i] += 3,再让 diff[j+1] -= 3 即可,只要花费 O(1) 的时间修改 diff 数组,就相当于给 nums 的整个区间做了修改。

注意:

1、差分数组的第一个元素和原数组一样,本质上是差分数组的数学公式逆推得到的结果。

把差分数组抽象成一个工具类便于调用,包含__init_构造方法和 increment 方法和 result 方法,代码如下:

//java codes
// 差分数组工具类
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];
        }
        // 用前缀和构造结果数组
        num = res[0];
        for (int i = 1; i < diff.length; i++) {
   
            num += diff[i]
            res[i] = num
        }
        return res;
    }
}

# python codes
# 差分数组工具类
class Difference:
    # 差分数组
    def __init__(self, nums: List[int]):
        assert len(nums) > 0 # 用断言捕获异常 比print好
        self.diff = [0] * len(nums) # O(n) 复杂度
        # 根据初始数组构造差分数组
        self.diff[0] = nums[0]
        for i in range(1, len(nums)):
            self.diff[i] = nums[i] - nums[i - 1]

    # 给闭区间 [i, j] 增加 val(可以是负数)
    def increment(self, i: int, j: int, val: int) -> None:
        self.diff[i] += val
        if j + 1 < len(self.diff):
            self.diff[j + 1] -= val

    # 返回结果数组
    def result(self) -> List[int]:
        res = [0] * len(self.diff)
        # 根据差分数组构造结果数组
        res[0] = self.diff[0]
        for i in range(1, len(self.diff)):
            res[i] = res[i - 1] + self.diff[i]
        return res

// c++ codes
// 差分数组工具类
class Difference {
    // 差分数组
    private:
        int* diff;
    
    /* 输入一个初始数组,区间操作将在这个数组上进行 */
    public:
        Difference(int* nums, int length) {
            assert(length > 0);
            diff = new int[length]();
            diff[0] = nums[0];
            for (int i = 1; i < length; i++) {
                diff[i] = nums[i] - nums[i - 1];
            }
        }

        /* 给闭区间 [i, j] 增加 val(可以是负数)*/
        void increment(int i, int j, int val) {
            diff[i] += val;
            if (j + 1 < sizeof(diff) / sizeof(diff[0])) {
                diff[j + 1] -= val;
            }
        }

        /* 返回结果数组 */
        int* result() {
            int* res = new int[siz
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

计算机魔术师

在校大二学生,请多多指教

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值