首页 > 其他分享 >前缀和与差分数组

前缀和与差分数组

时间:2024-03-27 13:22:06浏览次数:20  
标签:前缀 nums self 差分 len 数组 diff

目录

前缀和应用场景:原始数组不会被修改的情况下,频繁查询某个区间的累加和。
eg:计算数组下标2到5的数组和,原本用for循环,有了前缀和直接用5的前缀和减去2的前缀和得到答案,可以将O(n)的复杂度降为O(1)

一维前缀和

  • 图解

preSum=[0]*(len(nums+1))#初始化前缀和数组,若nums是原数组
for i in range(1,len(preSum)):# 计算 nums 的累加和
    preSum[i]=preSum[i-1]+nums[i-1]#当前的前缀和等于前一个前缀和加上原数组的当前值(减一是因为索引移位了)

二维前缀和

  • 图解

  • 计算每个矩阵 [0, 0, i, j] 的元素和

# 定义:preSum[i][j] 记录 matrix 中子矩阵 [0, 0, i-1, j-1] 的元素和
    def __init__(self, matrix: List[List[int]]):
        m, n = len(matrix), len(matrix[0])
        if m == 0 or n == 0: return
        # 构造前缀和矩阵
        self.preSum = [[0 for _ in range(n+1)] for _ in range(m+1)]
        for i in range(1, m+1):
            for j in range(1, n+1):
                # 计算每个矩阵 [0, 0, i, j] 的元素和
                self.preSum[i][j] = self.preSum[i-1][j] + self.preSum[i][j-1] + matrix[i-1][j-1] - self.preSum[i-1][j-1]

差分数组应用场景:频繁对原始数组的某个区间的元素进行增减。
eg:输入一个数组 nums,然后又要求给区间 nums[2..6] 全部加 1,再给 nums[3..9] 全部减 3,再给 nums[0..4] 全部加 2...求最后nums。解:构造差分数组=nums[i]
-nums[i-1],想对区间 nums[i..j] 的元素全部加 3,那么只需要让 diff[i] += 3,然后再让 diff[j+1] -= 3.详细解释如下

差分数组

  • 图解:

diff = [0] * len(nums)
# 构造差分数组
diff[0] = nums[0]
for i in range(1, len(nums)):
    diff[i] = nums[i] - nums[i - 1]

差分数组反推出原始数组

res = [0] * len(diff)
# 根据差分数组构造结果数组
res[0] = diff[0]
for i in range(1, len(diff)):
    res[i] = res[i - 1] + diff[i]
  • 对区间 nums[i..j] 的元素全部加 3,那么只需要让 diff[i] += 3,然后再让 diff[j+1] -= 3,详细解释:diff[i] += 3 意味着给 nums[i..] 所有的元素都加了 3,然后 diff[j+1] -= 3 又意味着对于 nums[j+1..] 所有元素再减 3,那综合起来,是不是就是对 nums[i..j] 中的所有元素都加 3

差分数组模板

# 差分数组工具类
class Difference:
    # 差分数组
    def __init__(self, nums: List[int]):
        assert len(nums) > 0
        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]

    # 给闭区间 [i, j] 增加 val(可以是负数)
    def increment(self, i: int, j: int, val: int) -> None:
        self.diff[i] += val
        if j + 1 < len(self.diff):
            self.diff[j + 1] -= val

    # 返回结果数组
    def result(self) -> List[int]:
        res = [0] * len(self.diff)
        # 根据差分数组构造结果数组
        res[0] = self.diff[0]
        for i in range(1, len(self.diff)):
            res[i] = res[i - 1] + self.diff[i]
        return res

标签:前缀,nums,self,差分,len,数组,diff
From: https://www.cnblogs.com/lushuang55/p/18098556

相关文章

  • 一本通差分约束入门题
    最关键的就是找好所有的要满足的不等式条件,注意隐含的条件还有一点就是注意没有源点建立源点#2436. 「SCOI2011」糖果#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;usingpii=pair<int,int>;#defineintlonglongconstintN=5e5+10,M......
  • 前缀和算法讲解(二)
    首先,大家看一下一维的前缀和:https://blog.csdn.net/hjyowl/article/details/136580832?spm=1001.2014.3001.5502今天,我们讲解一下二维的前缀和.先看题:输入一个 n 行 m 列的整数矩阵,再输入 q 个询问,每个询问包含四个整数 x1,y1,x2,y2,表示一个子矩阵的左上角坐标和右下......
  • 【C语言】数组(一维、二维数组的简单介绍)
    数组(Array)数组概念数组是一组相同数据类型元素的集合,属于一种简单的数据结构,从中可以得到三个有效信息数组元素是同一数据类型的变量数组存放一个或者多个数据,但是数组元素个数不能为0数组中各元素可独立作为一个基本变量使用注:数组分为一维数组和多维数组,多维数组一......
  • Java数组(下)
    Java数组(下)多维数组多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组inta[][]=newint[2][5];//可以看成是一个两行五列的数组packagearray;publicclassArrayDemo05{publicstaticvoidmain(String[]args......
  • Leetcode 和为k的子数组
    Day11第一题#######解题思路:两层循环,用暴力法解决(从不同起始位置开始的子数组)classSolution{publicintsubarraySum(int[]nums,intk){//和为k的子数组的个数计数器countintcount=0;for(intj=0;j<nums.length;j++){......
  • 小阳同学刷题日记-209. 长度最小的子数组
        题目: 给定一个含有 n 个正整数的数组和一个正整数 target 。找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl,numsl+1,...,numsr-1,numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。    惯例,献上我自......
  • 数据结构-数组
    数组是一种最为常见和应用广泛的数据结构,不用语言的数组不太一样,对于js的数组来说,和python的列表极其类似,都是可动态拓展值和类型的,还是来大致总结一下这个基础数据结构.创建数组letarr1=newArray('a','b',66)letarr2=['a','b',66]console.log(arr1......
  • 十八 1265. 数星星 (树状数组)
    1265.数星星(树状数组)思路:本题要统计每个星星左下角星星的数目,由于星星按y坐标增序给出,y坐标相同的按x坐标增序给出,所以不用关注y,可以视作每个x位置有几颗星星就为几的数组,每次统计左侧前缀和,再将当前计算的星星x位置数加一,使用树状数组(推荐视频:五分钟丝滑动画讲解|树状数......
  • 代码随想录算法训练营day34 | leetcode 1005. K 次取反后最大化的数组和、134. 加油站
    目录题目链接:1005.K次取反后最大化的数组和-简单题目链接:134.加油站-中等题目链接:135.分发糖果-困难题目链接:1005.K次取反后最大化的数组和-简单题目描述:给你一个整数数组nums和一个整数k,按以下方法修改该数组:选择某个下标i并将nums[i]替换为-nums[i]。重......
  • LeetCodeHot100 数组 53. 最大子数组和 56. 合并区间 238. 除自身以外数组的乘积
    53.最大子数组和https://leetcode.cn/problems/maximum-subarray/description/?envType=study-plan-v2&envId=top-100-likedpublicintmaxSubArray(int[]nums){int[]dp=newint[nums.length];dp[0]=nums[0];for(inti=1;i<nums......