1. 深度优先搜索(DFS)算法解析
深度优先搜索(Depth-First Search)是图论和树结构中最基础的遍历算法之一。我第一次接触DFS是在解决迷宫问题时——想象你站在迷宫的入口处,选择一条路径一直走到尽头,遇到死胡同就回退到上一个岔路口,这种"不撞南墙不回头"的策略正是DFS的核心思想。
与广度优先搜索(BFS)的"层层推进"不同,DFS采用"纵深探索"的方式,其典型应用场景包括:
- 路径查找(如迷宫求解)
- 拓扑排序
- 连通分量检测
- 解决回溯问题(如八皇后、数独)
- 生成排列组合
python复制# 最基本的DFS递归实现模板
def dfs(node, visited):
if node in visited: # 终止条件
return
visited.add(node) # 处理当前节点
for neighbor in node.neighbors:
dfs(neighbor, visited) # 递归访问相邻节点
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. DFS的核心实现机制
2.1 递归与栈的辩证关系
DFS最直观的实现方式是递归,这利用了系统调用栈自动保存上下文的特性。但递归存在栈溢出风险,当处理深度超过1000层的树结构时(如链状树),Python默认递归深度会抛出RecursionError。
迭代式实现则显式使用栈数据结构:
python复制def dfs_iterative(start):
stack = [start]
visited = set()
while stack:
node = stack.pop()
if node not in visited:
visited.add(node)
# 注意邻接节点逆序入栈以保证遍历顺序
for neighbor in reversed(node.neighbors):
stack.append(neighbor)
关键细节:邻接节点的入栈顺序决定了遍历方向。若要维持与递归相同的访问顺序,需要先将邻接节点逆序排列。
2.2 时间复杂度分析
DFS的时间复杂度取决于图的表示方式:
- 邻接表:O(V+E)(V为顶点数,E为边数)
- 邻接矩阵:O(V²)
空间复杂度主要来自:
- 递归调用栈/显式栈:O(V)
- 访问标记集合:O(V)
3. 典型应用场景实战
3.1 全排列问题
以数字[1,2,3]的全排列为例,DFS通过"选择-递归-撤销"的三部曲实现回溯:
python复制def permute(nums):
res = []
def backtrack(path, choices):
if not choices:
res.append(path.copy())
return
for i in range(len(choices)):
path.append(choices[i]) # 做选择
backtrack(path, choices[:i]+choices[i+1:]) # 递归
path.pop() # 撤销选择
backtrack([], nums)
return res
