一、DFS
算法模板
递归问题可以画一个树来写,递归不要去思考全过程,只思考三步:
1. 看当前层的操作
2. 看第一层如何到第二层——递归过程
3. 然后看根节点是如何结束的——递归出口
def dfs(i): if 条件成立: 收集结果 return for 集合元素: 处理节点 递归函数 回溯操作
1. 子集型回溯
特点:每个元素可选可不选
例1.1 子集
给你一个整数数组
nums
,数组中的元素 互不相同 。返回该数组所有可能的子集
(幂集)。解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例 1:
输入:nums = [1,2,3] 输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]示例 2:
输入:nums = [0] 输出:[[],[0]]代码1:以结果的思维来写:
class Solution: def subsets(self, nums: List[int]) -> List[List[int]]: n=len(nums) if n==0: return [[]] res=[] path=[] def dfs(i): res.append(path.copy()) if i==n: return for j in range(i,n): path.append(nums[j]) dfs(j+1) path.pop() dfs(0) return res
代码2:选和不选来写
class Solution: def subsets(self, nums: List[int]) -> List[List[int]]: n=len(nums) if n==0: return [[]] res=[] path=[] def dfs(i): if i==n: res.append(path.copy()) return dfs(i+1) path.append(nums[i]) dfs(i+1) path.pop() dfs(0) return res
例1.2 分割回文串
给你一个字符串
s
,请你将s
分割成一些子串,使每个子串都是回文串。返回s
所有可能的分割方案。示例 1:
输入:s = "aab" 输出:[["a","a","b"],["aa","b"]]示例 2:
输入:s = "a" 输出:[["a"]]提示:
1 <= s.length <= 16
s
仅由小写英文字母组成代码:
class Solution: def partition(self, s: str) -> List[List[str]]: n=len(s) res=[] path=[] #是否选择第i个和第i+1之间的"," def dfs(i,start): if i==n: res.append(path.copy()) return #最后一个逗号一定要选a,a,b, if i<n-1: dfs(i+1,start) #选 x=s[start:i+1] if x[::-1]==x: path.append(x) dfs(i+1,i+1) path.pop() dfs(0,0) return res
2. 组合型回溯(剪枝)
特点:从n个数中选出k个数的组合(可进行剪枝)
例1.1 递归实现组合型枚举
代码:
n,m=map(int,input().split()) res=[] path=[] def dfs(i): if i==n: if len(path)==m: res.append(path.copy()) return dfs(i+1) path.append(i+1) dfs(i+1) path.pop() dfs(0) res=res[::-1] for i in res: for j in i: print(j,end=" ") print()
3. 排列型回溯
特点:所有的数进行排列组合(全排列)
个数为:n!
和组合的区别:组合中不区分元素顺序
例3.1:全排列
给定一个不含重复数字的数组
nums
,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。示例 1:
输入:nums = [1,2,3] 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]示例 2:
输入:nums = [0,1] 输出:[[0,1],[1,0]]示例 3:
输入:nums = [1] 输出:[[1]]思路:
只看第一层选1,选2,选3可知,每一层是选择s集合中的数字,并且每次选择都要删除上一次选择的数。
递归出口是个数为nums长度。
代码:
class Solution: def permute(self, nums: List[int]) -> List[List[int]]: res=[] path=[] n=len(nums) def dfs(i,s): #递归结束 if i==n: res.append(path.copy()) return for x in s:#取s中的每一个元素 path.append(x) dfs(i+1,s-{x})#删除取过的元素 path.pop()#回溯 dfs(0,set(nums)) return res
二、BFS
算法模板
def BFS(): q = [] # 队列 st = [] # 判重数组,可以顺便记录步数 q.append(初始状态) while len(q)!=0: q.pop(0) #队头出列 for 扩展t : var:新节点 if 到达出口: return step if 满足要求: var入列 st[var]标记 return -1
三、 Flood fill
dir=[[0,1],[0,-1],[1,0],[-1,0]]
def dfs(x,y):
res=1
mp[x][y]="#"
for i in range(4):
nx,ny=x+dir[i][0],y+dir[i][1]
if nx>=h or nx<0 or ny>=w or ny<0:
continue
if mp[nx][ny]=="#":
continue
if mp[nx][ny]==".":
mp[nx][ny]="#"
res+=dfs(nx,ny)
return res
while True:
w,h=map(int,input().split())
if w==0 and h==0:
break
mp=[[0 for j in range(w)]for i in range(h)]
res=0
for i in range(h):
l=list(input())
for j in range(w):
mp[i][j]=l[j]
if l[j]=="@":
x,y=i,j
print(dfs(x,y))