当前位置: 首页 > news >正文

区间修改 - 差分

文章目录

  • 问题描述
  • 暴力解法
  • 差分数组优化
    • 核心思想
    • 区间修改的技巧
    • 代码实现
  • 总结

问题描述

最近在刷题的时候,遇到了一类区间修改的问题,刚开始用暴力法做,结果TLE了。后来学了差分数组这个技巧,解决的是区间修改问题,发现效率提升巨大。今天整理一下,分享给大家。
在这里插入图片描述

暴力解法

最直接的想法就是老老实实遍历区间,一个一个改:

public class BruteForce {public static void rangeUpdate(int[] arr, int left, int right, int val) {for (int i = left; i <= right; i++) {arr[i] += val;}}public static void main(String[] args) {int[] arr = {1, 2, 3, 4, 5};rangeUpdate(arr, 1, 3, 2);System.out.println("操作1后: " + Arrays.toString(arr));rangeUpdate(arr, 2, 4, -1);System.out.println("操作2后: " + Arrays.toString(arr));}
}

这种方法简单粗暴,但是效率不高: 时间复杂度:O(m*n),m是操作次数,n是数组长度。

差分数组优化

核心思想

差分数组的精髓在于:用差值来表示数组,把区间修改变成两个点的修改

什么意思呢?假设原数组是[1, 2, 3, 4, 5],它的差分数组是:

diff[0] = 1        // arr[0] = 1
diff[1] = 1        // arr[1] - arr[0] = 1
diff[2] = 1        // arr[2] - arr[1] = 1
diff[3] = 1        // arr[3] - arr[2] = 1
diff[4] = 1        // arr[4] - arr[3] = 1

神奇的地方来了:原数组就是差分数组的前缀和

arr[0] = diff[0] = 1
arr[1] = diff[0] + diff[1] = 1+1 = 2
arr[2] = diff[0] + diff[1] + diff[2] = 1+1+1 = 3
...

区间修改的技巧

要给区间[left, right]都加上val,只需要:

  1. diff[left] += val
  2. diff[right+1] -= val

为什么这样就行了?因为当我们计算前缀和还原数组时:

  • 从left开始,每个位置都会多加val
  • 从right+1开始,又会减掉val,抵消了

代码实现

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);int n = in.nextInt();int m = in.nextInt();long[] a = new long[n + 1];long[] diff = new long[n + 2];for (int i = 1; i <= n; i++) {a[i] = in.nextLong();diff[i] = a[i] - a[i - 1];}while (m-- > 0) {int l = in.nextInt();int r = in.nextInt();long k = in.nextLong();diff[l] += k;diff[r + 1] -= k;}for (int i = 1; i <= n; i++) {a[i] = a[i - 1] + diff[i];}for (int i = 1; i <= n; i++) {System.out.print(a[i] + " ");}}
}

总结

差分数组虽然听起来高大上,但本质就是一个很朴素的思想:用差值来描述变化,通过前缀和来还原状态。它的优势在于把O(n)的区间修改变成了O(1)的操作,当操作次数很多时,效率提升非常明显。

http://www.dtcms.com/a/325870.html

相关文章:

  • 在Linux中使用docker-compose快速搭建Prometheus监控系统
  • foreach 块并行加速
  • 澳洲增高营养品排行榜
  • 小波卷积YYDS!小波变换+CNN创新结合
  • 无人机航拍数据集|第11期 无人机人员行为目标检测YOLO数据集1868张yolov11/yolov8/yolov5可训练
  • 【bug】diff-gaussian-rasterization Windows下编译 bug 解决
  • STM32 HAL库驱动0.96寸OLED屏幕
  • 【学习】DCMM认证从“跟风“到“生存法则“的进化
  • EI检索-学术会议 | 人工智能、虚拟现实、可视化
  • react中父子数据流动和事件互相调用(和vue做比较)
  • 小杰python高级(three day)——matplotlib库
  • 关于微信小程序的笔记
  • 告别“焊武帝”时代!30-65W零外围A+C快充协议正式上线
  • Cherryusb UAC例程对接STM32内置ADC和PWM播放音乐和录音(下)=>UAC+STM32 ADC+PWM实现录音和播放
  • TradingAgents-CN: 基于多智能体的中文金融交易决策框架
  • Apache Ignite超时管理核心组件解析
  • XX生产线MES系统具体实施方案
  • 第2节 大模型分布式推理架构设计原则
  • react+echarts实现图表展示的两种方法
  • uni-app app端安卓和ios如何申请麦克风权限,唤起提醒弹框
  • 初识影刀:将多个相同格式EXCEL中内容汇总到一个EXCEL文件中去
  • HRM分层推理模型在医疗AI上的应用探析
  • LeetCode算法日记 - Day 8: 串联所有单词的子串、最小覆盖子串
  • 学习嵌入式-IMX6ULL学习——中断
  • 防火墙组网方式总结
  • 阿里发布数字人模型echomimic_v3,在视频合成的基础上支持prompt输入~
  • 计算机组成原理2-5:C语言中的数据类型及转换
  • LangChain 框架 Parser 讲解
  • LeetCode 2438.二的幂数组中查询范围内的乘积:模拟(前缀和可选)
  • 十二、Linux Shell脚本:正则表达式