#单调栈 -> 解决「下一个更大元素」,「上一个更小元素」#注意1:找最近的比它小的数,需要维护单调递增栈,即栈顶元素比它大的全部弹出(对于i+1来说,他们的贡献不会比i大,所以没用了)。栈顶剩下的就是最近那个。然后自己再入栈。#注意2:找右边最近的比它小的数,需要逆序遍历。但栈依然是递增的。#注意4:一般栈里是存下标。#基本模板defst(nums):
st = []
for num in nums:
while st and num >= st[-1]: #递增 <= 递减
st.pop()
st.append(num)
#返回每一数下一个更大/小的数(list)defn_st(nums):
n = len(nums)
res= [0]*n #存结果
s = []
for i inrange(n-1,-1,-1): #正序遍历 逆序遍历都可 倒叙入栈==正序出栈while s and s[-1] <= num[i]:
# 矮个起开,反正也被挡着了。。。
s.pop()
res[i] = s[-1] if s else -1# nums[i] 身后的更大元素
s.append(nums[i])
return s
单调队列
#单调队列 解决滑动窗口最值
def wd(nums,k):
ans = []
q = deque() #使用双端队列for i in range(len(nums)):
#1. 入 3.记录答案whileqand nums[q[i]] <= x:
q.pop()
q.append(i)
#2.出if i-q[0] >= k: #窗口大小>= k
q.popleft() #队首移除窗口if i >= k-1:
ans.append(nums[q[0]]) #(队列递减,队首即最大值)return ans
#第二种
from collection import daque
def st(nums,k):
win = deque()
res= []
for i in range(len(nums)):
if i <k-1:
win.append(nums[i]) # 先将窗口前 k - 1 填满else:
# 窗口开始向前滑动# 移入新元素
win.append(nums[i])
# 将当前窗口中的最大元素记入结果
res.append(max(win))
# 移出最后的元素
win.popleft()
return res
差分
#差分#1.构建差分数组for i inrange(len(s)-1,0,-1):
s[i] -= s[i-1]
#2.转换加减(区间加减->端点加减)
s[l-1] += v
s[r] -= v
#3.前缀相加for i inrange(1,n):
s[i] += s[i-1]
eg:
# https://www.lanqiao.cn/problems/1276/learning/
n,q = map(int,input().split())
a = [0]+list(map(int,input().split()))
b = [0]*(n+2)
for i inrange(1,n+1):
b[i] = a[i] - a[i-1]
for i inrange(q):
l,r,x = map(int,input().split())
b[l] += x
b[r+1] -= x
for i inrange(1,n+1):
a[i] = b[i] + a[i-1]
if a[i] <= 0:
print(0,end =' ')
else:
print(a[i],end = ' ')
并查集
#并查集deffind(x):
# 如果x不是根节点,则递归地找到x的根节点,并将x的父节点更新为根节点(实现状态压缩)if x!= p[x]:
p[x] = find(p[x])
return p[x]
for i inrange(n):
a,b = map(int,input().split())
pa,pb = find(a),find(b) # 分别找到a和b的根节点if pa != pb:
p[pa] = pb
DFS
#深搜 1.确定dfs的两个参数 2.确认终止条件 3.处理目前搜索节点出发的路径
ans = []
defdfs(层数,参数):
if (出局判断,特况):
更新答案
return
剪枝
for (枚举下一层的情况):
if (vis[i]==0):
vis[i] = 1
dfs(层数+1,参数)#下一层
vis[i] = 0#回复状态,不影响回溯时的使用 #有时候没有显式地使用栈和回溯操作,但实际上通过递归调用实现了DFS的功能(全球变暖问题,岛屿类)。return
BFS
from collections import deque, defaultdict
t = ''.join(['0', '1', '2', '3', '4', '5', '6', '7', '8', 'x']) # 目标值
d = [-1, 1, -3, 3] # 上下移 在数组中步长为3
ls = ['0'] + list(map(str, input().split())) # 输入态
idx = ls.index('x') # x的初始索引#有时候需要加入falg变量 用于判断符合
vis = defaultdict(int) #判重数组一定要有!!!# 记录已经访问过的状态,避免重复访问同一个状态def bfs():
q = deque()
stp = 0# 初始步数
q.append([ls, idx, stp])
s = ''.join(ls)
vis[s] = 1
res = -1# 存储最终的结果while q:
ts, tidx, stp = q.popleft()
if''.join(ts) == t: # 等于目标值
res = stp
breakfor i in d:
tmp = ts.copy() # 原始状态的完整性,以便在搜索失败时回溯到上一个状态
nidx = tidx + i
# 出界情况if nidx < 1or nidx > 9: continueif (tidx == 3or tidx == 6) and i == 1: continueif (tidx == 4or tidx == 7) and i == -1: continue# 交换位置
tmp[tidx], tmp[nidx] = tmp[nidx], tmp[tidx]
stmp = ''.join(tmp)
if vis[stmp]: continue
vis[stmp] = 1
q.append([tmp, nidx, stp + 1])
print(res)
bfs()
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步