首页 > 其他分享 >差分数组

差分数组

时间:2022-11-16 23:12:54浏览次数:62  
标签:nums int self 差分 数组 diff

目录

简介

差分数组

与前缀和数组类似,差分数组里的每个元素,是原数组的后项与前项之差,即:

\[diff[i] = \begin{cases} nums[0], & i = 1\\ nums[i] - nums[i - 1], & i \geq 1\\ \end{cases} \]

如果已知差分数组,即可反推出原数组,即

\[nums[i] = diff[i] + nums[i - 1] \]

例如,设原数组\(nums = [1, 2, 3, 4, 5, 6, 7, 8]\),那么:

  • 差分数组d的计算方法:
diff[0] = nums[0]
for i in range(1, len(nums)):
    diff[i] = nums[i] - nums[i - 1]
  • 通过差分数组反推原始数组:
results = [0 for _ in range(len(diff))]
results[0] = diff[0]
for i in range(1, len(diff)):
    results[i] = results[i - 1] + diff[i]

上述过程,其实就是在对\(diff\)数组的前缀和的过程。

性质

它可以维护多次对序列的一个区间加上一个数,并在最后询问某一位的数或多次询问某一位的数

它主要适用于频繁对原始数组的某个区间内的所有元素进行增减

例如,对区间 \(nums[i:j]\) 所有元素加 \(k\),那么只需两步:

  • 要对 \(diff[i]\ +=\ k\),然后再对 \(diff[j + 1]\ -=\ k\) ;
  • 最后对 \(diff\) 求一遍前缀和即可。

通过差分数组,可以快速对区间进行增加的操作。

总结

差分数组工具类

差分算法,我们可以将其总结为一个工具类:

from typing import List

class Difference(object):
    def __init__(self):
        self.diff = list()

    def build(self, nums: List[int]):
        self.diff = [0] * len(nums)
        self.diff[0] = nums[0]
        for i in range(1, len(nums)):
            self.diff[i] = nums[i] - nums[i - 1]

    def increase(self, i: int, j: int, value: int):
        self.diff[i] += value
        if j + 1 < len(self.diff):
            self.diff[j + 1] -= value

    def result(self) -> List[int]:
        result = [0] * len(self.diff)
        result[0] = self.diff[0]
        for i in range(1, len(self.diff)):
            result[i] = result[i - 1] + self.diff[i]
        return result

应用

应用1:Leetcode.1109

题目

1109.航班预订统计

题目分析

原题可以转换为给定长度为 \(n\) 的数组 \(nums\),依次对区间 \([left,\ right]\) 里面的每一个元素增加 \(seats\),最后求修改后的数组。

代码实现

class Solution:
    def corpFlightBookings(self, bookings: List[List[int]], n: int) -> List[int]:
        """ 航班预订统计 """
        nums = [0] * n
        df = Difference()
        df.build(nums)
        for booking in bookings:
            # 注意:由于航班号是从1开始的,所以索引序号需要减一
            i = booking[0] - 1
            j = booking[1] - 1
            value = booking[2]
            df.increase(i, j, value)
        return df.result()

应用2:Leetcode.370

题目

370.区间加法

题目分析

为了求操作之后的数组,我们只需要对差分数组求前缀和,就可以得到原始数组。

代码实现

class Solution:
    def getModifiedArray(self, length: int, updates: List[List[int]]) -> List[int]:
        nums = [0] * length
        df = Difference()
        df.build(nums)
        for update in updates:
            df.increase(update[0], update[1], update[2])
        return df.result()

应用3:Leetcode.1094

题目

1094.拼车

题目分析

将行程中的公里数看成位置坐标,只需要记录有上下客的每个里程区间内的乘客数量,最后再求出乘客数最大的区间,看是否满足汽车的空位即可。

很明显,上下乘客的过程,就可以对区间做增加的过程,所以,直接利用差分数组的性质,计算差分数组,再通过差分数组,反推出原数组即可。

代码实现

MAX_MILE = 1001
class Solution:
    def carPooling(self, trips: List[List[int]], capacity: int) -> bool:
        nums = [0] * MAX_MILE
        df = Difference()
        df.build(nums)
        for trip in trips:
            # 由于乘客在trip[2]就下车了,所以实际乘客在车上的旅程为[trip[1], trip[2]-1]
            df.increase(trip[1], trip[2] - 1, trip[0])
        return max(df.result()) <= capacity

标签:nums,int,self,差分,数组,diff
From: https://www.cnblogs.com/larry1024/p/16897831.html

相关文章

  • 稀疏数组
    稀疏数组需求:编写五子棋游戏中,有存盘退出和续上盘的功能。分析问题:因为该二维数组的很多值是默认值0,因此记录了很多没有意义的数据。解决:稀疏数组(一种数据结构)......
  • PHP数组知识点整理
    */*Copyright(c)2016,烟台大学计算机与控制工程学院*Allrightsreserved.*文件名:text.cpp*作者:常轩*微信公众号:Worldhello*完成日期:2016年8月11日*版本号:V1......
  • 数组~筛法求素数
    题目描述用筛法求之N内的素数。 用筛法求素数的基本思想是:把从1开始的、某一范围内的正整数从小到大顺序排列,1不是素数,首先把它筛掉。剩下的数中选择最小的数是素数,然后......
  • 数组~冒泡法排序
    题目描述用冒泡法对10个整数从小到大排序。输入10个整数输出排序好的10个整数样例输入4853234453453451223012样例输出341230458512223434......
  • 数组~插队
    题目描述有一个按照升序已排好的9个元素的数组,今输入一个数要求按原来排序的规律将它插入数组中。输入第一行,原始数列。第二行,需要插入的数字。输出排序后的数列......
  • 数组~明明的随机数
    题目描述明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N≤100),对于其中重复的数字,只保留一个,把其余相同的数......
  • #yyds干货盘点# 动态规划专题:二维差分
    1.简述:描述给你一个n行m列的矩阵,下标从1开始。接下来有q次操作,每次操作输入5个参数x1,y1,x2,y2,k表示把以(x1,y1)为左上角,(x2,y2)为右下角的子矩阵的每个元素都加上k,......
  • #yyds干货盘点# LeetCode 腾讯精选练习 50 题:数组中的第K个最大元素
    题目:给定整数数组nums和整数k,请返回数组中第k个最大的元素。请注意,你需要找的是数组排序后的第k个最大的元素,而不是第k个不同的元素。你必须设计并实现时间复杂度......
  • leetcode26. 删除有序数组中的重复项(简单)
    题目:给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。由于在......
  • VUE对象数组,和普通数组的常用方法
    在VUE中也可以使用find,findIndex,map等方法对数组对象进行查询,赋值等操作,记录一下定义数组对象 vararrobj=[{"id":1,"keyword":"羽绒服","times":1000},{"id":2,"k......