首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >差分数组模板

差分数组模板

作者头像
全栈程序员站长
发布2022-09-06 18:21:02
发布2022-09-06 18:21:02
1K0
举报

大家好,又见面了,我是你们的朋友全栈君。

参考于 labuladong: 论那些小而美的算法技巧:差分数组

一、什么时候使用差分数组呢?

相信很多人都遇到过这类题: 给定一个原数组长度为 n,查询次数 m , 每次查询给定一个区间 [l ,r] 和一个整数 k , 使得原数组介于 [l ,r] 之间的元素同时 增 (或减) k 输出最终的数组

num[ 8 , 2 , 6 , 3 , 1 ] m = 2 1 3 1 0 2 3 注: 第一次查询 num = 8 3 7 4 1 第二次查询 num = 11 6 10 4 1 最终 num = 11 6 10 4 1

当然了,每次查询,遍历一下区间 [l ,r] 对其进行修改,结果肯定是对的 但是呢,笔试 和 刷题 时,如果数据给的比较大,比较严苛,多数是会超时,时间复杂度是 O(mn)

二、什么是差分数组 ?

这时就需要用到了差分数组的技巧来解答, 差分数组 : 主要适用场景是频繁对原始数组的某个区间的元素进行增减。 1、首先 构造差分数组 diff ,diff [ i ] = num [ i ] – num [ i – 1 ]

代码语言:javascript
复制
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];
}

通过这个diff差分数组是可以反推出原始数组nums的,代码逻辑如下:

代码语言:javascript
复制
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、这样构造差分数组 diff,就可以 快速进行区间增减的操作,如果你想对 区间 [ i , j ] 的元素全部加 3,那么只需要让 diff[ i ] += 3,然后再让 diff[ j + 1 ] -= 3 即可:

原理很简单,回想 diff 数组反推 nums 数组的过程diff [ i ] += 3 意味着给 nums [ i… ] 所有的元素都加了 3,然后 diff [ j + 1 ] -= 3 又意味着对于 nums [ j + 1… ] 所有元素再减 3,那综合起来,是不是就是对 nums [ i … j ] 中的所有元素都加 3 了 。 只要花费 O(1) 的时间修改 diff 数组,就相当于给 nums 的整个区间做了修改。多次修改diff,然后通过 diff 数组反推,即可得到 nums 修改后的结果。

代码语言:javascript
复制
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];
        }
        return res;
    }
}

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/134177.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年6月7,如有侵权请联系 cloudcommunity@tencent.com 删除
目录
  • 一、什么时候使用差分数组呢?
  • 二、什么是差分数组 ?
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档