当前位置: 首页 > 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.lryc.cn/news/617469.html

相关文章:

  • 大模型中的反向传播是什么
  • 网络编程~
  • 【13-向量化-高效计算】
  • 《番外:Veda的备份,在某个未联网的旧服务器中苏醒……》
  • 飞算 JavaAI 智能进阶:从技术工具到金融科技开发范式的革新
  • 文件操作:fgets与gets区别+fread/fwrite +流定位接口
  • 【图像处理基石】PCA图像压缩与还原:基于OpenCV的Lena图实验
  • 2025 算法面试试题-阿里面试题分析
  • 【算法专题训练】11、字符串中的变位词
  • PyTorch基础(使用Tensor及Antograd实现机器学习)
  • GraalVM !拥抱云原生的 JVM
  • foreach 块并行加速
  • docker compose和docker-compose命令的区别
  • 力扣164:最大间距
  • 大数据系统架构模式:驾驭海量数据的工程范式
  • React(四):事件总线、setState的细节、PureComponent、ref
  • LeetCode 2438.二的幂数组中查询范围内的乘积:模拟(前缀和可选)
  • C++项目实战(日期类的实现)
  • MFC C++ 使用ODBC方式调用Oracle数据库的详细步骤
  • 重学React(五):脱围机制一
  • 金蝶云星辰:赋能企业数据管理
  • spring boot 整合redis教程
  • 带简易后台管理的米表系统 域名出售系统 自适应页面
  • 帝国理工学院团队研发:Missense3D-PTMdb—— 解析遗传变异与翻译后修饰的交互式工具
  • 计算机网络---交换机
  • 套接字技术、视频加载技术、断点续传技术
  • Horse3D引擎研发笔记(四):在QtOpenGL下仿three.js,封装EBO绘制四边形
  • 2025 年国内可用 Docker 镜像加速器地址
  • Rust面试题及详细答案120道(19-26)-- 所有权与借用
  • 《基于Pytorch实现的声音分类 :网页解读》