【ACWING】【2】前缀和+差分

前缀和

前缀和为前边所有元素的和,通过两个前缀和相减,可以得到任意连续子数组的和。
前缀和的长度比数组大1,为了保证最后一个索引也拥有前缀和。

和为k的子数组

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的连续子数组的个数 。

from collections import defaultdict
class Solution(object):
    def subarraySum(self, nums, k):
        ans = 0
        n = len(nums)
        presums = defaultdict(int)  # 这题只需要统计个数,故采用字典
        presums[0] = 1  # 初始化前缀和为0出现一次
        presum = 0
        for i in range(n):
            presum += nums[i]
            ans += presums[presum-k]
            presums[presum] += 1
        return ans

二维区域和检索 - 矩阵不可变/二维子矩阵的和

给定一个二维矩阵 matrix,以下类型的多个请求:
计算其子矩形范围内元素的总和,该子矩阵的 左上角 为 (row1, col1) ,右下角 为 (row2, col2) 。
实现 NumMatrix 类:
NumMatrix(int[][] matrix) 给定整数矩阵 matrix 进行初始化
int sumRegion(int row1, int col1, int row2, int col2) 返回 左上角 (row1, col1) 、右下角 (row2, col2) 所描述的子矩阵的元素 总和 。

class NumMatrix(object):
    def __init__(self, matrix):
        m, n = len(matrix), len(matrix[0])
        self.presum = [[0 for _ in range(n+1)] for _ in range(m+1)]
        for i in range(m):
            for j in range(n):
                self.presum[i+1][j+1] = self.presum[i][j+1] \
                + self.presum[i+1][j] - self.presum[i][j] + matrix[i][j]

    def sumRegion(self, row1, col1, row2, col2):
        return self.presum[row2+1][col2+1]-self.presum[row1][col2+1] \
        -self.presum[row2+1][col1]+self.presum[row1][col1]

差分

差分是前缀和的逆操作,用于处理连续子数组频繁加减操作,将On时间复杂度降为O1(相对于频繁操作而言,倘若只有一次加减操作,从差分还原为原数组时间复杂度也是On)。

区间加法

假设你有一个长度为 n 的数组,初始情况下所有的数字均为 0,你将会被给出 k​​​​​​​ 个更新的操作。
其中,每个操作会被表示为一个三元组:[startIndex, endIndex, inc],你需要将子数组 A[startIndex … endIndex](包括 startIndex 和 endIndex)增加 inc。
请你返回 k 次操作后的数组。

class Solution(object):
    def getModifiedArray(self, length, updates):
        # 差分方法,用于解决多次子连续数组加减操作
        # 差分为前缀和的逆操作
        # 原数组  a0 a1 ... an
        # 差分 b0=a0 b1=a1-a0 b2=a2-a1
        # 对[l,r]的inc可以只需要给l处的差分+c,给r+1处的差分-c
        diff = [0 for _ in range(length)]
        for l,r,inc in updates:
            diff[l] += inc
            if r+1 <= length-1: diff[r+1] -= inc
        ans = [0 for _ in range(length)]
        for i in range(length):
            ans[i] = ans[i-1] + diff[i] if i > 0 else diff[i]
        return ans

航班预订统计

这里有 n 个航班,它们分别从 1 到 n 进行编号。
有一份航班预订表 bookings ,表中第 i 条预订记录 bookings[i] = [firsti, lasti, seatsi] 意味着在从 firsti 到 lasti (包含 firsti 和 lasti )的 每个航班 上预订了 seatsi 个座位。
请你返回一个长度为 n 的数组 answer,里面的元素是每个航班预定的座位总数。
first和last从1索引开始,程序里需要-1

class Solution(object):
    def corpFlightBookings(self, bookings, n):
        diff = [0 for _ in range(n)]
        for first, last, seats in bookings:
            diff[first-1] += seats
            if last<=n-1:
                diff[last] -= seats
        for i in range(1,n):
            diff[i] = diff[i] + diff[i-1]
        return diff

拼车

车上最初有 capacity 个空座位。车 只能 向一个方向行驶(也就是说,不允许掉头或改变方向)
给定整数 capacity 和一个数组 trips , trip[i] = [numPassengersi, fromi, toi] 表示第 i 次旅行有 numPassengersi 乘客,接他们和放他们的位置分别是 fromi 和 toi 。这些位置是从汽车的初始位置向东的公里数。
当且仅当你可以在所有给定的行程中接送所有乘客时,返回 true,否则请返回 false。
这题和上边的不同是这题toi处就下车,故为r为toi-1

class Solution(object):
    def carPooling(self, trips, capacity):
        peoples = [0 for _ in range(1001)]
        far = 0
        for numi, fromi, toi in trips:
            far = max(toi,far)
            peoples[fromi] += numi
            peoples[toi] -= numi
        if peoples[0] > capacity: return False
        for i in range(1,far):
            peoples[i] = peoples[i] + peoples[i-1]
            if peoples[i] > capacity: return False
        return True
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值