数据结构、算法刷题笔记(4)(小白零基础、自用学习笔记)差分数组篇python实现

刷题系列内容均是对labuladong公众号的理解和刷题代码解读,如果看不明白直接搜labuladong

差分数组的主要适用场景是频繁对原始数组的某个区间的元素进行增减

例如:

输入一个数组nums,然后又要求给区间nums[2..6]全部加 1,再给nums[3..9]全部减 3,再给nums[0..4]全部加 2,最后nums数组的值是什么?

如果用for 循环,时间复杂度是 O(N),效率会很低下。

这里就需要差分数组的技巧,类似前缀和技巧构造的prefix数组,我们先对nums数组构造一个diff差分数组,diff[i]就是nums[i]和nums[i-1]之差

※nums.insert(0,0) #在数组前添0

diff = [nums[i]-nums[i-1] for i in range(1,len(nums))]

我们可以根据diff数组推出原来的数组:

num = [0 for i in range(len(diff)+1)]

for i in range(len(diff)):

num[i+1] = num[i] + diff[i]

这样构造差分数组diff,就可以快速进行区间增减的操作,如果你想对区间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 了。

也就是说,想要得到最初的给区间数组加减操作,需要一下三步:

①构造整个数组的差分数组diff

②将diff[i]和diff[j+1]修改(看题目要求,是一次还是多次)

③推回原数组

例题分析:

代码解析:

def update(length,updates):

nums = [0 for i in range(length)]#初始化数组

result = []

for up in updates:#进行多次操作

result.append(increment(nums,up[0],up[1],up[2]))

nums = result[-1]#每次操作之后将更新值赋值到原数组中

return nums

def increment(nums,start,end,inc):

#计算差分数组

nums.insert(0,0)

diff = [nums[i]-nums[i-1] for i in range(1,len(nums))]

#将diff[i]和diff[j+1]修改

diff[start] = diff[start] + inc

if end < len(nums)-2:

diff[end+1] = diff[end+1] - inc

#推回原数组

num = [0 for i in range(len(diff)+1)]

for i in range(len(diff)):

num[i+1] = num[i] + diff[i]

return num[1:]

代码解析:

class Solution:

def corpFlightBookings(self, bookings: List[List[int]], n: int) -> List[int]:

# 构造差分数组

nums=[0]*(n+1)

diff = [nums[i] - nums[i - 1] for i in range(1, len(nums))]

for first,last,seats in bookings: #多次更改差分数组

first = first-1

last = last -1

diff[first] = diff[first] + seats

if last < len(nums) - 2:

diff[last+1] = diff[last+1] - seats

#回退差分数组

num = [0 for i in range(len(diff) + 1)]

for i in range(len(diff)):

num[i+1] = num[i] + diff[i]

nums = num[1:]

return nums

解题思路:

trips数组就对应了一次区间操作,[2,1,5]在节点1和节点5之间给数组加上2。提示中给的长度是1000,那我们可以想象这个数组长度是1000,trips是在这个数组上的区间操作,成功接送乘客是指每次操作之后,全部数值都不能大于numPassengers。

注意![2,1,5]不包含节点5!!!到这个点乘客已经下车了!!!

代码解析:

class Solution:

def carPooling(self, trips: List[List[int]], capacity: int) -> bool:

#构造差分数组

nums = [0]*1001

diff = [nums[i]- nums[i-1] for i in range(1,len(nums))]#其实可以简单的让diff = [0] * 1000,但是我为了训练这个熟练度,因为有时候nums这个数组给定且不是全0,还是需要计算diff的。

#更改差分数组

for numPassengers,From,to in trips:

diff[From] = diff[From] + numPassengers

if to < len(nums)-1: #如果[i,j]不包括节点j,则这里减1

diff[to] = diff[to] - numPassengers

#回退差分数组

num = [0]*1001

for i in range(len(diff)):

num[i+1] = num[i]+diff[i]

lastnum = num[1:]

p = sum(i>capacity for i in lastnum ) #用来判断是否有超过capacity的数值

if p:

return False

else:

return True

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值