leetcode刷题的差分数组技巧【Python】
2 差分数组
差分数组的主要适用场景是频繁对原始数组的某个区间的元素进行增减。常规思路是用for循环实现,时间复杂度为O(n)。用差分数组可将时间复杂度降为O(1)。具体做法为先构建差分数组diff,diff[i]=nums[i]-nums[i-1]
nums=[8,2,6,3,1]
diff =[nums[0]]
for i in range(1,len(nums)):
diff.append(nums[i]-nums[i-1])
print(diff)
通过差分数组也可以反推出原始数组nums
res = [diff[0]]
for i in range(1,len(diff)):
res.append(diff[i]+res[i-1])
print(res)
如果对nums[i:j+1]的元素全部+3,那么只要diff[i] += 3,然后diff[j+1] -= 3即可。
370.区间加法(中等)
假设你有一个长度为 n 的数组,初始情况下所有的数字均为 0,你将会被给出 k个更新的操作。
其中,每个操作会被表示为一个三元组:[startIndex, endIndex, inc],你需要将子数组 A[startIndex … endIndex](包括 startIndex 和 endIndex)增加 inc。
请你返回 k 次操作后的数组。
示例:
输入: length = 5, updates = [[1,3,2],[2,4,3],[0,2,-2]]
输出: [-2,0,3,5,3]
解释:
初始状态: [0,0,0,0,0]
进行了操作 [1,3,2] 后的状态: [0,2,2,2,0]
进行了操作 [2,4,3] 后的状态: [0,2,5,5,3]
进行了操作 [0,2,-2] 后的状态: [-2,0,3,5,3]
class Difference(object):
def __init__(self,nums):
self.nums=nums
def diff_gen(self):
"""生成差分数组"""
diff=[self.nums[0]]
for i in range(1,len(self.nums)):
diff.append(self.nums[i]-self.nums[i-1])
return diff
def nums_res(self,i,j,val):
"""还原数组"""
diff = self.increment(i,j,val)
res =[diff[0]]
for i in range(1,len(diff)):
res.append(diff[i]+res[i-1])
return res
def increment(self,i,j,val):
"""区间加法"""
diff = self.diff_gen()
diff[i] += val
if len(diff)>j+1:
diff[j+1] -= val
return diff
if __name__=='__main__':
updates = [[1,3,2],[2,4,3],[0,2,-2]]
length = 5
nums=[0]*length
d = Difference(nums)
for i in range(len(updates)):
diff=d.nums_res(updates[i][0],updates[i][1],updates[i][2])
d = Difference(diff)
print(diff)
简单解法:
class Solution(object):
def getModifiedArray(self, length, updates):
"""
:type length: int
:type updates: List[List[int]]
:rtype: List[int]
"""
res = [0 for _ in range(length + 1)]
for update in updates:
start, end, inc = update[0], update[1], update[2]
res[start] += inc
res[end + 1] -= inc
for i in range(1, length):
res[i] += res[i - 1]
return res[:-1]
if __name__=='__main__':
length=5
updates = [[1,3,2],[2,4,3],[0,2,-2]]
d = Solution()
print(d.getModifiedArray(length,updates))
1109.航班预订统计(中等)
这里有 n 个航班,它们分别从 1 到 n 进行编号。
有一份航班预订表 bookings ,表中第 i 条预订记录 bookings[i] = [firsti, lasti, seatsi] 意味着在从 firsti 到 lasti (包含 firsti 和 lasti )的 每个航班 上预订了 seatsi 个座位。
请你返回一个长度为 n 的数组 answer,其中 answer[i] 是航班 i 上预订的座位总数。
示例 1:
输入:bookings = [[1,2,10],[2,3,20],[2,5,25]], n = 5
输出:[10,55,45,25,25]
解释:
航班编号 1 2 3 4 5
预订记录 1 : 10 10
预订记录 2 : 20 20
预订记录 3 : 25 25 25 25
总座位数: 10 55 45 25 25
因此,answer = [10,55,45,25,25]
1 2 3 4 5 6 7 8 9
示例 2:
输入:bookings = [[1,2,10],[2,2,15]], n = 2
输出:[10,25]
解释:
航班编号 1 2
预订记录 1 : 10 10
预订记录 2 : 15
总座位数: 10 25
因此,answer = [10,25]
#直接套用上述框架,注意航班编号是从1开始
class Difference(object):
def __init__(self,nums):
self.nums=nums
def diff_gen(self):
"""生成差分数组"""
diff=[self.nums[0]]
for i in range(1,len(self.nums)):
diff.append(self.nums[i]-self.nums[i-1])
return diff
def nums_res(self,i,j,val):
"""还原数组"""
diff = self.increment(i,j,val)
res =[diff[0]]
for i in range(1,len(diff)):
res.append(diff[i]+res[i-1])
return res
def increment(self,i,j,val):
"""区间加法"""
diff = self.diff_gen()
diff[i] += val
if len(diff)>j+1:
diff[j+1] -= val
return diff
if __name__=='__main__':
bookings = [[1,2,10],[2,3,20],[2,5,25]]
n = 5
nums=[0]*n
d = Difference(nums)
for i in range(len(bookings)):
diff=d.nums_res(bookings[i][0]-1,bookings[i][1]-1,bookings[i][2])
d = Difference(diff)
print(diff)
1094.拼车(中等)
假设你是一位顺风车司机,车上最初有 capacity 个空座位可以用来载客。由于道路的限制,车 只能 向一个方向行驶(也就是说,不允许掉头或改变方向,你可以将其想象为一个向量)。
这儿有一份行程计划表 trips[][],其中 trips[i] = [num_passengers, start_location, end_location] 包含了你的第 i 次行程信息:
必须接送的乘客数量;
乘客的上车地点;
以及乘客的下车地点。
这些给出的地点位置是从你的 初始 出发位置向前行驶到这些地点所需的距离(它们一定在你的行驶方向上)。
请你根据给出的行程计划表和车子的座位数,来判断你的车是否可以顺利完成接送所用乘客的任务(当且仅当你可以在所有给定的行程中接送所有乘客时,返回 true,否则请返回 false)。
示例 1:
输入:trips = [[2,1,5],[3,3,7]], capacity = 4
输出:false
示例 2:
输入:trips = [[2,1,5],[3,3,7]], capacity = 5
输出:true
示例 3:
输入:trips = [[2,1,5],[3,5,7]], capacity = 3
输出:true
示例 4:
输入:trips = [[3,2,7],[3,7,9],[8,3,9]], capacity = 11
输出:true
提示:
你可以假设乘客会自觉遵守 “先下后上” 的良好素质
trips.length <= 1000
trips[i].length == 3
1 <= trips[i][0] <= 100
0 <= trips[i][1] < trips[i][2] <= 1000
1 <= capacity <= 100000
#直接套用上述框架,注意航班编号是从1开始
class Difference(object):
def __init__(self,nums):
self.nums=nums
def diff_gen(self):
"""生成差分数组"""
diff=[self.nums[0]]
for i in range(1,len(self.nums)):
diff.append(self.nums[i]-self.nums[i-1])
return diff
def nums_res(self,i,j,val):
"""还原数组"""
diff = self.increment(i,j,val)
res =[diff[0]]
for i in range(1,len(diff)):
res.append(diff[i]+res[i-1])
return res
def increment(self,i,j,val):
"""区间加法"""
diff = self.diff_gen()
diff[i] += val
if len(diff)>j+1:
diff[j+1] -= val
return diff
def solution(arr,capacity):
nums=[0]*1000
d = Difference(nums)
for i in range(len(arr)):
diff=d.nums_res(arr[i][1],arr[i][2]-1,arr[i][0])
d = Difference(diff)
#print(diff)
for j in diff:
if j>capacity:
return False
else:
continue
return True
if __name__=='__main__':
trips = [[2,1,5],[3,3,7]]
capacity = 4
print( solution(trips,capacity))
trips = [[2,1,5],[3,3,7]]
capacity = 5
print( solution(trips,capacity))
trips = [[2,1,5],[3,5,7]]
capacity = 3
print( solution(trips,capacity))
trips = [[3,2,7],[3,7,9],[8,3,9]]
capacity = 11
print( solution(trips,capacity))
简单解法:
def solution(arr,capacity):
nums=[0]*1000
for i in range(len(arr)):
for j in range(arr[i][1],arr[i][2]):
nums[j] += arr[i][0]
#print(diff)
for x in nums:
if x>capacity:
return False
else:
continue
return True
if __name__=='__main__':
trips = [[2,1,5],[3,3,7]]
capacity = 4
print( solution(trips,capacity))
trips = [[2,1,5],[3,3,7]]
capacity = 5
print( solution(trips,capacity))
trips = [[2,1,5],[3,5,7]]
capacity = 3
print( solution(trips,capacity))
trips = [[3,2,7],[3,7,9],[8,3,9]]
capacity = 11
print( solution(trips,capacity))