首页 > 其他分享 >从入门到精通——差分数组

从入门到精通——差分数组

时间:2024-10-16 20:19:18浏览次数:3  
标签:入门 int max 差分 数组 ans diff

差分数组

差分数组通常是指一个数组,其中每个元素是原数组中对应元素与前一个元素的差。这种数组在处理序列数据时非常有用,尤其是在需要计算连续项之间的变化或者进行数据压缩时。
定理解释
差分数组的一个核心定理是,给定一个差分数组,可以唯一地重建原始数组。这意味着,如果你有一个差分数组,你可以通过累加的方式恢复原始数组。这个定理的成立基于以下几个步骤:
差分数组的构建:假设有一个原始数组 A[1…n],我们可以构建一个差分数组 D[1…n],其中 D[i] = A[i] - A[i-1],对于 i = 2, 3, …, n,且 D[1] = A[1](或者可以选择 D[1] = 0,如果 A[1] 是相对于某个已知的起始值)。
原始数组的重建:给定差分数组 D[1…n],我们可以重建原始数组 A[1…n],方法是从 A[1] = D[1] 开始,然后对于每个 i(2 ≤ i ≤ n),计算 A[i] = A[i-1] + D[i]。
这个定理的证明是直接的,因为你可以通过反向操作来验证重建的数组是否与原始数组相同。从 A[1] 开始,使用差分数组中的每个差值逐步累加,最终得到的 A[n] 应该与原始数组的最后一个元素相同。
应用场景:
1.数据压缩:减少存储空间,特别是在数据变化不大时。
2.快速求和:快速计算数组中任意一段区间的和。
3.更新和查询:在数组中快速更新值并查询特定统计信息。
4.游戏开发:处理游戏中角色位置等动态变化的数据。
5.信号处理:在音频或视频编辑中表示信号的变化。

下面解释了差分数组进行区间修改图示方便大家理解~
在这里插入图片描述
下面写几个力扣的题目方便大家练习
2848. 与车相交的点

class Solution {
    public int numberOfPoints(List<List<Integer>> nums) {
        int max=0;
        for(List<Integer> p : nums)max = Math.max(max,p.get(1));
        int[] diff = new int[max + 2];
        for (List<Integer> interval : nums) {
            diff[interval.get(0)]++;
            diff[interval.get(1) + 1]--;
        }
        int num=0;
        int s=0;
        for(int t:diff){
            s+=t;
            if(s>0)num++;
        }
        return num;
    }
}

1094. 拼车

class Solution {
    public boolean carPooling(int[][] trips, int capacity) {
        int[] d=new int[1001];
        for(int [] t:trips){
            int num = t[0], start = t[1], end = t[2];
            d[start]+=num;
            d[end]-=num;//不包括end
        }
        int s=0;
        for(int t:d){
            s+=t;
            if(s>capacity)return false;
        }
        return true;
    }
}

1893. 检查是否区域内所有整数都被覆盖

class Solution {
    public boolean isCovered(int[][] ranges, int left, int right) {
        int[] diff = new int[52];
        //对差分数组进行处理
        for(int i = 0; i < ranges.length; i++){
            diff[ranges[i][0]]++;
            diff[ranges[i][1]+1]--;
        }
        //根据差分数组处理前缀和,为理解方便单独定义sum,可以原地做
        int[] sum = new int[52];
        for(int i = 1; i <= 51; i++){
            sum[i] = sum[i-1] + diff[i];
        }
        //从left到right判断是否满足sum > 0
        for(int i = left; i <= right; i++){
            if(sum[i] <= 0) return false;
        }
        return true;
    }
}

1109. 航班预订统计

class Solution {
    public int[] corpFlightBookings(int[][] bookings, int n) {
        int[] c = new int[n + 1];
        for (int[] bo : bookings) {
            int l = bo[0] - 1, r = bo[1] - 1, v = bo[2];
            c[l] += v;
            c[r + 1] -= v;
        }
        int[] ans = new int[n];
        ans[0] = c[0];
        for (int i = 1; i < n; i++) {
            ans[i] = ans[i - 1] + c[i];
        }
        return ans;
    }
}

2406. 将区间分为最少组数

class Solution {
   public int minGroups(int[][] intervals) {
    int max = intervals[0][1];
    for (int[] interval : intervals) {
        max = Math.max(max, interval[1]);
    }
    int[] diff = new int[max + 1];
    for (int[] interval : intervals) {
        diff[interval[0]] += 1;
        if (interval[1] + 1 <= max) {
            diff[interval[1] + 1] -= 1;
        }
    }
    int t = 0, ans = 0;
    for (int i = 1; i <= max; i++) {
        t = t + diff[i];
        ans = Math.max(ans, t);
    }
    return ans;
}
}

1589. 所有排列中的最大和

class Solution {
    public int maxSumRangeQuery(int[] nums, int[][] requests) {
        int p = (int)1e9 + 7;
        int n = nums.length;
        long ans = 0;
        int[] diff = new int[n + 1];
        Arrays.sort(nums);
        for (int i = 0; i < requests.length; i++) {
            diff[requests[i][0]]++;
            diff[requests[i][1] + 1]--;
        }
        for (int i = 0; i < n; i++) {
            diff[i + 1] += diff[i];
        }
        Arrays.sort(diff);
        for (int i = n; i >= 1 && diff[i] > 0; i--) {
            ans += (long)diff[i] * nums[i - 1];
            ans %= p;
        }
        return (int)ans;
    }
}

二维差分
2536. 子矩阵元素加 1

class Solution {
    public int[][] rangeAddQueries(int n, int[][] queries) {
        // 二维差分
        int[][] diff = new int[n + 2][n + 2];
        for (int[] q : queries) {
            int r1 = q[0], c1 = q[1], r2 = q[2], c2 = q[3];
            diff[r1 + 1][c1 + 1]++;
            diff[r1 + 1][c2 + 2]--;
            diff[r2 + 2][c1 + 1]--;
            diff[r2 + 2][c2 + 2]++;
        }

        // 计算 diff 的二维前缀和(原地修改),然后填入 ans
        int[][] ans = new int[n][n];
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                diff[i][j] += diff[i][j - 1] + diff[i - 1][j] - diff[i - 1][j - 1];
                ans[i - 1][j - 1] = diff[i][j];
            }
        }
        return ans;
    }
}

标签:入门,int,max,差分,数组,ans,diff
From: https://blog.csdn.net/w287586/article/details/142986953

相关文章

  • 黑客 如何攻破一个网站?长文图解全流程,零基础入门到精通,收藏这篇就够了
    一篇科普文,很适合小白,长文请静下心看。通过本文你将了解黑客常用的入手思路和技术手法,适合热爱网络信息安全的新手朋友了解学习。本文将从最开始的信息收集开始讲述黑客是如何一步步的攻破你的网站和服务器的。阅读本文你会学到以下内容:1.渗透测试前的简单信息收集。2.s......
  • 【CTF-SHOW】Web入门 Web27-身份证日期爆破 【关于bp intruder使用--详记录】
    1.点进去是一个登录系统,有录取名单和学籍信息发现通过姓名和身份证号可以进行录取查询,推测录取查询可能得到学生对应学号和密码,但是身份证号中的出生日期部分未知,所以可以进行爆破2.打开bp抓包这里注意抓的是学院录取查询系统发送POST类型进行查询的包,第一遍抓不到很正......
  • Vue详细入门(语法【二】)
    今天的学习目标!!!el挂载点data数据对象Vue实例生命周期1.beforeCreate2.created3.beforeMount4.mounted5.beforeUpdate6.updated7.beforeDestroy8.destroyed  在前面Vue详细入门(语法【一】)当中我们学习了什么是Vue,Vue是怎么使用的嘞,Vue有哪些指令,它的核心语......
  • Js数组&高阶函数
    数组也是一种复合数据类型,在数组可以存储多个不同类型的数据数组中存储的是有序的数据,数组中的每个数据都有一个唯一的索引可以通过索引来操作获取数据数组中存储的数据叫做元素任何类型的值都可以成为数组中的元素基本操作创建数组//通过Array创建数组constarr=ne......
  • rust学习一、入门之搭建简单开发环境
    最近希望学习一些新的,选择了rust.本篇介绍怎么搭建一个非常简单的windows开发环境,以及如何使用cargo命令1、搭建开发环境(windows11)a.登录官网https://www.rust-lang.org/tools一看就明白,此处略。b.安装rustup一看就明白,此处略。c.安装cargoscriptcargoinstallcargo......
  • etcd入门到实战
    概述:本文将介绍etcd特性、使用场景、基本原理以及Linux环境下的实战操作入门什么是etcd?etcd是一个分布式键值存储数据库关键字解析:键值存储:存储协议是key—value的形式,类似于redis分布式:具有分布式特性、每个etcd实例作为集群中的一个节点,通过分布式锁,leader选举保......
  • 前缀和和差分归纳总结
    前缀和数组可以在O(1)的时间内求得某一区间中的所有数据的和差分数组可以在O(1)的时间内对某一区间中的所有数据进行加减操作原数组求差分及为差分数组,差分数组再求前缀和即为原数组一维前缀和:设原数组为a[N],前缀和数组为s[N],数组下标都从1开始存储每个s[i]等于a[1]......
  • JAVA入门必备知识点!!你入门了吗?
    目录技术能力考核——答案一、缓存中间件(一)理论部分请简述你熟悉的一种缓存中间件(如Redis)的底层数据结构,并举例说明其在实际应用中的优势。解释缓存穿透、缓存击穿和缓存雪崩的概念,并分别阐述应对这些问题的策略。在分布式系统中,如何保证缓存与数据库的数据一致性?请列......
  • <Leetcode:算法题及解析>最大子数组和(Javascript版)
    题目描述:给你一个整数数组nums,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。子数组是数组中的一个连续部分。本题可以使用Kadane's算法实现,这是一种用于解决最大子数组和问题的高效算法。它由JosephBornKadane在1984年提出。这个算法的核......
  • Python入门:A+B问题
    1.A+B问题I前言本篇作为课程第一篇,主要是对Python基础语法进行扫盲,本节课会学习到下面知识:输入本道题目的工作任务很简单,只是计算两个数的和,但是在计算之前,我们首先要明确的一个问题就是如何把这两个数据输入到计算机中,并由程序读取呢?输入当然是使用键盘之类的输入设备完......