模拟
根据题目意思,捋清整个流程,使用代码去模拟整个流程
例题
种花问题
class Solution:
def canPlaceFlowers(self, flowerbed: List[int], n: int) -> bool:
# 模拟,在数组前后各添加1个0,从第1个元素到倒数第2个元素,判断元素是否为0且左右都为0则可插入
flowerbed.insert(0,0)
flowerbed.append(0)
res=0
for i in range(1,len(flowerbed)-1):
if flowerbed[i]==0 and flowerbed[i-1]==0 and flowerbed[i+1]==0:
res+=1
flowerbed[i]=1
return res>=n
哈希表
用于存储键值对的数据结构,Python的“字典”数据类型就是基于哈希表实现的。
作用:以空间换时间,快速判断一个元素是否出现在集合中
例题
K 和数对的最大数目
class Solution:
def maxOperations(self, nums: List[int], k: int) -> int:
# 使用字典统计每个数字的个数,配对成功则个数-1
dt={}
for i in nums:
if i in dt:
dt[i]+=1
else:
dt[i]=1
res=0
for i in nums:
if dt[i]!=0:
dt[i]-=1
if dt.get(k-i,0)!=0:
res+=1
dt[k-i]-=1
return res
双指针解法
class Solution:
def maxOperations(self, nums: List[int], k: int) -> int:
# 排序+双指针
nums.sort()
res=0
l=0
r=len(nums)-1
while l<r:
if nums[l]+nums[r]==k:
res+=1
l+=1
r-=1
elif nums[l]+nums[r]>k:
r-=1
else:
l+=1
return res
前缀和
数组前n个数之和
作用:求区间和
维护前缀和数组
nums=range(100) # 需要求区间和的数组
n=len(nums)
preSum=[0]*(n+1) # 初始化长度为n+1的前缀和数组
for i in nums:
preSum[i+1]=preSum[i]+nums[i] # 维护前缀和数组
例题
子数组最大平均数 I
class Solution:
def findMaxAverage(self, nums: List[int], k: int) -> float:
# 前缀和数组
n=len(nums)
if n==k:
return sum(nums)/k
preSum=[0]*(n+1)
for i in range(n):
preSum[i+1]=preSum[i]+nums[i]
l=0
res=float("-inf")
for i in range(n-k+1):
res=max(preSum[i+k]-preSum[i],res)
return res/k
滑动窗口
滑动窗口,顾名思义,窗口大小可以不固定,使用左右指针,作为窗口的左右边界。
滑动窗口模板
def findSubArray(nums):
N = len(nums) # 数组/字符串长度
left, right = 0, 0 # 双指针,表示当前遍历的区间[left, right],闭区间
sums = 0 # 用于统计 子数组/子区间 是否有效,根据题目可能会改成求和/计数
res = 0 # 保存最大的满足题目要求的 子数组/子串 长度
while right < N: # 当右边的指针没有搜索到 数组/字符串 的结尾
sums += nums[right] # 增加当前右边指针的数字/字符的求和/计数
while 区间[left, right]不符合题意: # 此时需要一直移动左指针,直至找到一个符合题意的区间
sums -= nums[left] # 移动左指针前需要从counter中减少left位置字符的求和/计数
left += 1 # 真正的移动左指针,注意不能跟上面一行代码写反
# 到 while 结束时,我们找到了一个符合题意要求的 子数组/子串
res = max(res, right - left + 1) # 需要更新结果
right += 1 # 移动右指针,去探索新的区间
return res
例题
最大连续1的个数 III
class Solution:
def longestOnes(self, nums: List[int], k: int) -> int:
# 滑动窗口
n=len(nums)
if n-sum(nums)<=k: # 数组中0的总个数不大于容忍数,则可全部反转
return n
res=0
l,r=0,0
zeros=0 # 统计lr区间0的个数
while r<n:
if nums[r]==0:
zeros+=1 # 区间中出现0,计数加1
while zeros>k: # 当区间中0的个数超过能容忍的反转数
if nums[l]==0: #如果左端点的值为0,则左端点右移,区间0的个数减1
zeros-=1
l+=1 # 左端点右移
res=max(res,r-l+1)
r+=1 # 右端点右移
return res