差分数组模板

差分数组模板参考于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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • discuz整站搬家

    discuz整站搬家网站建设中难免遇到要更换服务器和站点搬家,这里分享下  1、首先我们需要登录DZ论坛后台,在全局设置里边,关闭站点,防止网站出现新数据导致备份数据不完整。如图:  2、后台-站长,点击数据库,按照提示,选择备份类型,点击提交开始进行备份。  3、备份完成之后我们可以看到如下图。  4、接下来我们需要把整个网站进行压缩打包,打包完成之后把压缩包…

    2022年7月17日
    32
  • navicat premium注册和激活码-激活码分享

    (navicat premium注册和激活码)JetBrains旗下有多款编译器工具(如:IntelliJ、WebStorm、PyCharm等)在各编程领域几乎都占据了垄断地位。建立在开源IntelliJ平台之上,过去15年以来,JetBrains一直在不断发展和完善这个平台。这个平台可以针对您的开发工作流进行微调并且能够提供…

    2022年3月31日
    5.0K
  • shiro面试知识点总结_jmeter面试常见问题

    shiro面试知识点总结_jmeter面试常见问题Shiro总结和常见面试题一、 什么是shiroShiro是一个强大易用的java安全框架,提供了认证、授权、加密、会话管理、与web集成、缓存等功能,对于任何一个应用程序,都可以提供全面的安全服务,相比其他安全框架,shiro要简单的多。二、 Shiro的核心概念Subject、SecurityManager、RealmSubject:主体,代表了当前“用户”,这个用户不一定是一个具体的…

    2022年10月14日
    2
  • Qt中使用Json

    Qt中使用Json

    2021年11月19日
    64
  • java认证考试题目_java程序员工资一般多少

    java认证考试题目_java程序员工资一般多少第一部分基础知识练习目标本章对应于《学生指南》各章的内容分别提供了练习题集,包括:●第一章Java入门●第二章数据类型和运算符●第三章流程控制与数组●第四章封装●第五章继承

    2022年8月3日
    25
  • oracle number类型的数值存储空间是几个字节?

    oracle number类型的数值存储空间是几个字节?其实有公式可以计算:number(p,s)占用得空间为:length=floor((p+1)/2)+1备注:如果该数值为负数,需要再加一个字节。—————-例如:NUMBER(14,4)的类型数值,存储空间为selectfloor((14+1)/2)+1fromdual结果输出为:8

    2022年7月24日
    8

发表回复

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

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