首页 > 编程语言 >【进阶算法】差分

【进阶算法】差分

时间:2023-11-05 19:47:25浏览次数:37  
标签:arr 进阶 val int 差分 算法 数组 diff

差分是一种类似于前缀和的编码技巧,可以快速实现对数组某个区间的所有元素增加或减少一个值。

一、差分数组

示例:数组 arr = [8,1,3,-2,5,0,-3,6],输入 m 个操作,每个操作输入 (L , R, val),表示对数组的 [L, R] 区间中每个元素增加 val,要求输出最后的 arr 数组。

比如,第 1 次操作,输入 (0 , 2, 1);第 2 次操作,输入 (2 , 5, 3);第 3 次操作,输入 (0 , 6, -1)。最后,arr = [8,1,6,0,7,2,-4,6]。

常规的思路很容易想到,每次遍历区间 [L, R],给每个元素加上 val,但是每次遍历数组,时间复杂度比较高。可以使用差分数组提高处理效率。

 

差分思想:

定义一个差分数组 diff[arr.len],其中 diff[0] = arr[0],diff[i] = arr[i] - arr[i - 1],表示原数组中每个元素与前一个元素的差值。

/**
 * 构造差分数组
 *
 * @param arr 原数组
 * @return 差分数组
 */
private int[] diff(int[] arr) {
    int len = arr.length;
    int[] diff = new int[len];
    diff[0] = arr[0];
    for (int i = 1; i < len; i++) {
        diff[i] = arr[i] - arr[i - 1];
    }
    return diff;
}

 

差分数组的前缀和就是原数组。

/**
 * 根据差分数组反推原数组
 *
 * @param diff 差分数组
 * @return 原数组
 */
private int[] original(int[] diff) {
    int len = diff.length;
    int[] arr = new int[len];
    arr[0] = diff[0];
    for (int i = 1; i < len; i++) {
        arr[i] = arr[i - 1] + diff[i];
    }
    return arr;
}

 

通过差分数组可以快速对原数组某个区间的所有元素增加或减少一个值,比如,给原数组 [L, R] 区间每个元素增加 val,只需要 diff[L] += val, diff[R + 1] -= val 即可。根据差分数组反推原数组的过程可知,diff[L] += val 代表给原数组 L 之后的所有元素增加了 val,diff[R + 1] -= val 代表给原数组 R + 1 之后的所有元素都减少了 val,所以最终是给 [L, R] 区间中的每个元素增加了 val。

 

二、代码实现

// 原数组
int[] arr = {8, 1, 3, -2, 5, 0, -3, 6};
// 差分数组
int[] diff = diff(arr);

/**
 * 构造差分数组
 *
 * @param arr 原数组
 * @return 差分数组
 */
private int[] diff(int[] arr) {
    int len = arr.length;
    int[] diff = new int[len];
    diff[0] = arr[0];
    for (int i = 1; i < len; i++) {
        diff[i] = arr[i] - arr[i - 1];
    }
    return diff;
}

/**
 * 给原数组 [left, right] 区间每个元素增加 val
 *
 * @param left  区间左边界
 * @param right 区间右边界
 * @param val   增加的数值
 */
public void increment(int left, int right, int val) {
    diff[left] += val;
    if (right + 1 < diff.length) {
        diff[right + 1] -= val;
    }
}

/**
 * 根据差分数组计算修改后的原数组
 *
 * @param diff 差分数组
 * @return 修改后的原数组
 */
private int[] original(int[] diff) {
    int len = diff.length;
    int[] arr = new int[len];
    arr[0] = diff[0];
    for (int i = 1; i < len; i++) {
        arr[i] = arr[i - 1] + diff[i];
    }
    return arr;
}

 

三、适用场景

差分数组的适用场景:

  频繁对原始数组的某个区间所有元素进行增减操作

 

四、练习题目

LeetCode 370.区间加法

假设你有一个长度为 n 的数组,初始情况下所有的数字均为 0,你将会被给出 k​​​​​​ 个更新的操作。

其中,每个操作会被表示为一个三元组:[startIndex, endIndex, inc],你需要将子数组 A[startIndex ... endIndex](包括 startIndex 和 endIndex)增加 inc

请你返回 k 次操作后的数组。

示例:

输入: length = 5, updates = [[1,3,2],[2,4,3],[0,2,-2]]
输出: [-2,0,3,5,3]

解释:

初始状态:
[0,0,0,0,0]

进行了操作 [1,3,2] 后的状态:
[0,2,2,2,0]

进行了操作 [2,4,3] 后的状态:
[0,2,5,5,3]

进行了操作 [0,2,-2] 后的状态:
[-2,0,3,5,3]

 

LeetCode 1109. 航班预订统计

LeetCode 1094. 拼车

 

标签:arr,进阶,val,int,差分,算法,数组,diff
From: https://www.cnblogs.com/luwei0424/p/17810748.html

相关文章

  • 排序算法
    快速排序......
  • 文心一言 VS 讯飞星火 VS chatgpt (128)-- 算法导论11.1 3题
    三、用go语言,试说明如何实现一个直接寻址表,表中各元素的关键字不必都不相同,且各元素可以有卫星数据。所有三种字典操作(INSERT、DELETE和SEARCH)的运行时间应为O(1)(不要忘记DELETE要处理的是被删除对象的指针变量,而不是关键字。)文心一言,代码正常运行:在Go语言中,我们可以使......
  • ACM竞赛常用算法模板(C++)
    1.快速排序AcWing785.快速排序:https://www.acwing.com/problem/content/787/题目描述给定你一个长度为n的整数数列。请你使用快速排序对这个数列按照从小到大进行排序。并将排好序的数列按顺序输出。输入格式输入共两行,第一行包含整数n。第二行包含n个整数(所有整数均在1∼10......
  • 数据结构与算法—绪论
    前言数据结构与算法是程序员内功体现的重要标准之一,且数据结构也应用在各个方面,业界更有程序=数据结构+算法这个等式存在。各个中间件开发者,架构师他们都在努力的优化中间件、项目结构以及算法提高运行效率和降低内存占用,在这里数据结构起到相当重要的作用。此外数据结构也蕴含一......
  • 算法进阶
    贪心算法定义是指在对问题求解时,总是做出当前看来是最好的选择,着眼于眼前(做出目前对自己好的:贪心),不从整体最优上考虑,做出某种意义上的局部最优解。但有时贪心算法的解就是最优解。要会判断一个问题是否用贪心算法来计算。例题找零问题:假设商店老板需要找零n元钱,钱币的面额有:1......
  • 排序算法
    一、选择排序12,23,8,15,33,24,77,558,23,12,15,33,24,77,558,12,23,15,33,24,77,558,12,15,23,33,24,77,558,12,15,23,24,33,77,558,12,15,23,24,33,55,77二、冒泡排序12,23,8,15,33,24,77,5512,23,8,15,33,24,55,7712,23,8,15,24,33,55,7712,8,23,15,24,33,55,7712,8,15,23,......
  • 用欧几里得算法求两个数的最大公约数
    一.什么是欧几里得算法1.欧几里得算法就是辗转相除法,用于求两个数的最大公约数。如果用gcd(a,b)表示a和b的最大公约数,gcd(a,b)=gcd(b,a%b),当a%b==0时,b就是最大公约数。2.算法说明:首先按照大小输入两个整数a、b,再用一个中间量用来存放二者的余数。计算后将b的值赋给a,将余数赋给b......
  • 【教3妹学编程-算法题】使数组变美的最小增量运算数
    2哥 :3妹,脸上的豆豆好了没呢。3妹:好啦,现在已经没啦2哥 :跟你说很快就会消下去的,还不信~既然你的容颜和心情都如此美丽,那我们就再做一道关于美丽的题吧。3妹:切,2哥就会取笑我,伤心时让我做题,开心时也让我做题! 1题目: 给你一个下标从0开始、长度为n的整数数组nums,和一个整......
  • c++实现排序算法
    排序算法选择排序#include<iostream>#include<cmath>usingnamespacestd;intmain(){ intn,i,j,a[2000]; boolt; cin>>n; for(i=1;i<=n;i++) cin>>a[i]; for(i=1;i<n;i++) for(j=i+1;j<=n;j++) if......
  • 【python进阶】14大模块200页知识体系md笔记,第4篇:linux命令进阶(2)
    本文从14大模块展示了python高级用的应用。分别有Linux命令,多任务编程、网络编程、Http协议和静态Web编程、html+css、JavaScript、jQuery、MySql数据库的各种用法、python的闭包和装饰器、mini-web框架、正则表达式等相关文章的详细讲述。完整版笔记直接地址:请移步这里共14......