差分数组模板

差分数组模板参考于labuladong:论那些小而美的算法技巧:差分数组一、什么时候使用差分数组呢?相信很多人都遇到过这类题:给定一个原数组长度为n,查询次数m,每次查询给定一个区间[l,r]和一个整数k,使得原数组介于[l,r]之间的元素同时增(或减)k输出最终的数组num[8,2,6,3,1]m=2131023注:第一次查询num=83741第二次查询num=1161041最终num=1

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

参考于 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 ]

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的,代码逻辑如下:

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 修改后的结果。

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.net/134177.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • mysql慢查询sql统计_mysql服务启动慢

    mysql慢查询sql统计_mysql服务启动慢一、概述MySQL的慢查询日志是MySQL提供的一种日志记录,它用来记录在MySQL中响应时间超过阀值(long_query_time,单位:秒)的SQL语句。默认情况下,MySQL不启动慢查询日志。本文简单介绍如何开启慢查询日志,如何用mysqldumpslow分析慢查询。二、慢查询日志设置1、临时设置临时开启慢查询日志(重启失效)setglobalslow_query_log=on;注…

    2022年10月14日
    0
  • 如何用idftp遍历整个目录—-下载、删除_delphi教程

    如何用idftp遍历整个目录—-下载、删除_delphi教程如何用idftp遍历整个目录—-下载、删除_delphi教程unitUnit1;interfaceusesWindows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,Dialogs,StdCtrls,IdBaseComponent,IdComponent,IdTCPConn…

    2022年6月18日
    20
  • 树莓派 Raspberry Pi 连接 WiFi

    树莓派 Raspberry Pi 连接 WiFi说明开启Wifi的不同情况说明:第一种情况:有显示器和鼠标键盘1.1:桌面操作开启WiFi,包含桌面图形的系统(RaspbianStretchwithdesktop)1.2:通过树莓派配置,适用带桌面或仅命令行的系统。1.3:直接修改配置文件,适用带桌面或仅命令行的系统。第二种情况:无显示器和鼠标键盘2.1:使用另一台可用电脑编辑SD卡(但我尝试不成功,ORZ,望…

    2022年5月18日
    40
  • C#文件和文件夹输入输出流代码

    1、建立一个文本文件1publicclassFileClass2{3publicstaticvoidMain()4{5WriteToFile();6}7stati

    2021年12月21日
    44
  • hdu4122(单调队列)

    hdu4122(单调队列)

    2021年8月24日
    60
  • 【谷粒商城】框架扩充篇(3/4)「建议收藏」

    【谷粒商城】框架扩充篇(3/4)「建议收藏」1.ELASTICSEARCH1、安装elasticsearchdokcer中安装elasticsearch(1)下载ealasticsearch和kibanadockerpullelasticsearch:7.6.2dockerpullkibana:7.6.2(2)配置mkdir-p/mydata/elasticsearch/configmkdir-p/mydata/elasticsearch/dataecho”http.host:0.0.0.0″>

    2022年5月19日
    39

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号