前缀和
前缀和为前边所有元素的和,通过两个前缀和相减,可以得到任意连续子数组的和。
前缀和的长度比数组大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