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

前缀和+差分数组

时间:2023-11-06 23:55:17浏览次数:44  
标签:arr 前缀 nums int sum 差分 数组 diff self

一、一维数组度前缀和--固定数组查询区间和

1.1 定义

对于给定一个数组arr(下标从0开始),它的前缀和S[i] 表示从arr[0]到arr[i]元素总和。

1.2 构造前缀和

S[i] = S[i-1] + arr[i-1]

1.3 应用-求某个区间的和

计算区间[i, j]的元素和 => arr[i] + arr[i+1] + arr[i+2] + …… + arr[j] = s[j] - S[i-1] (i > 0) 当i== 0 时 [0, j] 元素和等于s[j]

1.4模板题

1.4.1前缀和构造 1480. 一维数组的动态和 - 力扣(LeetCode)

class Solution:
    def runningSum(self, nums: List[int]) -> List[int]:
        # 原地修改
        for i in range(1, len(nums)):
            nums[i] = nums[i-1] + nums[i]
        return nums

1.4.2求区间和303. 区域和检索 - 数组不可变 - 力扣(LeetCode)

class NumArray:

    def __init__(self, nums: List[int]):
        self.nums = nums
        for i in range(1, len(nums)):
            self.nums[i] = self.nums[i-1] + nums[i]


    def sumRange(self, left: int, right: int) -> int:
        if left == 0:
            return self.nums[right]
        else:
            return self.nums[right] - self.nums[left-1]

二、二维度数组前缀和-固定矩阵查询子矩阵元素和

2.1 定义

定义一个矩阵matrix 使得 \(sum_i,_j\) = \(\sum_1^i\)\(\sum_1^j\)matrix[i][j]
\(sum_i,_j\) 表示已matrix[i][j] 为做右下角,matrix[1][1] 为左上角顶点围起来的矩阵元素的和

2.2 构造二维矩阵前缀和

计算公式

\[sum_i,_j = sum_{i-1},_j + sum_i,_{j-1} - sum_{i-1},_{j-1} + matrix[i][j] \]

2.3 求子矩阵的区域元素和 以(\(x_1\), \(y_1\)) 为左上角 下标以(\(x_2\), \(y_2\)) 为右下角下标的区域元素和 res(x1 >= 1, y1>=1)

\[res = sum_{x2},_{y2} - sum_{x1-1},_{y2} - sum_{x2},_{y1-1} + sum_{x1-1},_{y1-1} \]

2.4 模板题

2.4.1 304. 二维区域和检索 - 矩阵不可变

class NumMatrix:

    def __init__(self, matrix: List[List[int]]):
        self.m = len(matrix) + 1
        self.n = len(matrix[0]) + 1
        self.sum = [[0 for i in range(self.n)] for i in range(self.m)]
        
        for i in range(1, self.m):
            for j in range(1, self.n):
                # 注意matrix数组下标是从0开始, self.sum[i][j] 对应的数组右下角下标为(i-1, j-1)
                self.sum[i][j] = self.sum[i-1][j] + self.sum[i][j-1] - self.sum[i-1][j-1] + matrix[i-1][j-1]

    def sumRegion(self, row1: int, col1: int, row2: int, col2: int) -> int:
        return self.sum[row2+1][col2+1] - self.sum[row2+1][col1] - self.sum[row1][col2+1] + self.sum[row1][col1] 

三、一维差分数组

3.1 定义

对于给定一维数组arr[n], 差分数组diff[i] = arr[i] - arr[i-1] (i>1)

3.2 构造差分数组

\[diff[0] = arr[0] \]

\[diff[i] = arr[i] - arr[i-1](i>0) \]

3.3 应用-频繁对某个区间的元素全部增加(减少)一个值

3.3.1对于在数组[l, r]区间上所有元素都加上val,只需要在差分数组上俩端点加(减)val即可

\[diff[l] += val \]

\[diff[r+1] -= val \]

3.3.2 如何求得在[l, r]区间加上val后 指定arr[i] (l <= i <= r)的值,根据差分数组定义,diff[i] = arr[i] - arr[i-1] 逆运算求和即可

\[arr[i] = \sum_{j=0}^idiff[j] \]

3.4 一维差分题目 1109. 航班预订统计

class Solution:
    def corpFlightBookings(self, bookings: List[List[int]], n: int) -> List[int]:
        # 一开始没有预定的座位, 因此差分数组diff 为[0] * n
        diff = [0] * n
        # 数组从1开始, 下标处理要减少1
        for first, last, incr in bookings:
            diff[first-1] += incr
            if last < n:
                diff[last] -= incr
        # 原地进行累加 arr[i] = (diff[0] + ... + diff[i-1]) + diff[i] = arr[i-1] + diff[i]
        for i in range(1,n):
            diff[i] += diff[i-1]
        
        return diff

四、二维差分数组

4.1 定义 一个二维数组arr[m][n]

\[diff[i][j] = arr[i][j] - arr[i-1][j] - arr[i][j-1] + arr[i-1][j-1](i > 1, j > 1) \]

4.2以左上角下标为(x1, y1), 右下角下标(x2, y2) 区域增加(减少)一个值val

\[diff[x1][y1] += val \]

\[diff[x2+1][y1] -= val \]

\[diff[x1][y2+1] -= val \]

\[diff[x2+1][y2+1] += val \]

4.3 求区域累加后结果数组

arr[i][j] 即求差分数组diff的前缀和sum[i][j] = \(\sum_1^i\sum_1^jdiff[i][j]\)

\[arr[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + diff[i][j] \]

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

class Solution:
    def rangeAddQueries(self, n: int, queries: List[List[int]]) -> List[List[int]]:
        diff = [[0] * (n+2) for i in range(n+2)]
        for x1, y1, x2, y2 in queries:
            diff[x1+1][y1+1] += 1
            diff[x2+2][y1+1] -= 1
            diff[x1+1][y2+2] -= 1
            diff[x2+2][y2+2] += 1
        
        # 原地求前缀和
        for i in range(1, n+1):
            for j in range(1, n+1):
                diff[i][j] = diff[i-1][j] + diff[i][j-1] - diff[i-1][j-1] + diff[i][j]
        
        diff = diff[1:-1]
        for i, row in enumerate(diff):
            diff[i] = row[1:-1]
        
        return diff
	```

标签:arr,前缀,nums,int,sum,差分,数组,diff,self
From: https://www.cnblogs.com/chen-pi/p/17813916.html

相关文章

  • C++二维数组输出3
    题目描述输入一个整数\(N\),输出一个N行N列的二维矩阵,矩阵中的元素按列用\(1\)~\(N\)\(∗\)\(N\)蛇形填充。输入格式一个整数\red{N}\(N\)(\(N<=10\))输出格式输出N行N列的矩阵,元素之间用一个空格隔开,行末不要有多余的空格。样例输入数据3输出数据123654789......
  • 数组
    数组伪代码integera[5]Setito0WHILE(i<5)Readina[5]Setitoi+1ReadnumSetpositionto0SetfoundtoFALSEWHILE(position<5ANDfoundisFALSE)IF(a[]equalsnum)Setf......
  • C++中如何返回数组类型数据
    错误示范:int*test01(){ intdata[3]={1,2,3}; returndata;}intmain(){ int*result=test01(); for(inti=0;i<3;i++){ cout<<result[i]<<'\t'; }}正确示范:int*test01(){// intdata[3]={1,2,3}; int*da......
  • 数据结构与算法-数组
    什么是数组在每一种编程语言中,基本都会有数组这种数据类型。不过,它不仅仅是一种编程语言中的数据类型,还是一种最基础的数据结构是一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据数组的特点低效的插入和删除数组为了保持内存数据的连续性,会导致插入......
  • L-4: 34--在排序数组中查找元素的第一个和最后一个位置
    给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值 target,返回 [-1,-1]。你必须设计并实现时间复杂度为 O(logn) 的算法解决此问题。 示例1:输入:nums=[5,7,7,8,8,10],tar......
  • C++使用冒泡排序算法对数组进行排序
     #include<iostream>//包含iostream库usingnamespacestd;//使用标准命名空间intmain(){//主函数intarr[]={5,3,2,8,6,7,1,4};//定义并初始化数组intn=sizeof(arr)/sizeof(arr[0]);//计算数组长度//使用冒泡排序算法对数组进......
  • java数组最大值
    参考文章:java数组求最大值在Java中,你可以通过遍历数组元素来找到数组中的最大值。以下是两种常见的方法:使用循环遍历数组publicclassMain{publicstaticvoidmain(String[]args){int[]array={10,5,8,2,7};//假设数组的第一个元素是最大......
  • 实验三 类与指针、数组
    1#pragmaonce2#include<iostream>34usingstd::cout;56usingstd::endl;78classPoint{910public:11Point(intx0=0,inty0=0);12~Point()=default;13intget_x()const;14intget_y()const;15vo......
  • 实验三:类与数组、指针。
    实验任务11#pragmaonce23#include<iostream>4usingstd::cout;5usingstd::endl;67classPoint{8public:9Point(intx0=0,inty0=0);10~Point()=default;1112intget_x()const;13intget_y()const;14......
  • 力扣905 按奇偶排序数组 C++ 双指针+一次遍历
    905.按奇偶排序数组classSolution{public:vector<int>sortArrayByParity(vector<int>&nums){inti=0,j=nums.size()-1;while(i<nums.size()-1&&i<j){while(i<j&&(nums[i]%2==0))i++;......