單調棧
#單調棧 -> 解決「下一個更大元素」,「上一個更小元素」
#注意1:找最近的比它小的數,需要維護單調遞增棧,即棧頂元素比它大的全部彈出(對於i+1來說,他們的貢獻不會比i大,所以沒用了)。棧頂剩下的就是最近那個。然後自己再入棧。
#注意2:找右邊最近的比它小的數,需要逆序遍歷。但棧依然是遞增的。
#注意4:一般棧裡是存下標。
#基本模板
def st(nums):
st = []
for num in nums:
while st and num >= st[-1]: #遞增 <= 遞減
st.pop()
st.append(num)
#返回每一數下一個更大/小的數(list)
def n_st(nums):
n = len(nums)
res= [0]*n #存結果
s = []
for i in range(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.記錄答案
while q and 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 in range(len(s)-1,0,-1):
s[i] -= s[i-1]
#2.轉換加減(區間加減->端點加減)
s[l-1] += v
s[r] -= v
#3.字首相加
for i in range(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 in range(1,n+1):
b[i] = a[i] - a[i-1]
for i in range(q):
l,r,x = map(int,input().split())
b[l] += x
b[r+1] -= x
for i in range(1,n+1):
a[i] = b[i] + a[i-1]
if a[i] <= 0:
print(0,end =' ')
else:
print(a[i],end = ' ')
並查集
#並查集
def find(x):
# 如果x不是根節點,則遞迴地找到x的根節點,並將x的父節點更新為根節點(實現狀態壓縮)
if x!= p[x]:
p[x] = find(p[x])
return p[x]
for i in range(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 = []
def dfs(層數,引數):
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
break
for i in d:
tmp = ts.copy() # 原始狀態的完整性,以便在搜尋失敗時回溯到上一個狀態
nidx = tidx + i
# 出界情況
if nidx < 1 or nidx > 9: continue
if (tidx == 3 or tidx == 6) and i == 1: continue
if (tidx == 4 or 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()