🧮 回溯算法 (Backtracking)
难度 / Difficulty: 中等 (Medium)
分类 / Category: 算法搜索 (Search Algorithm)
时间复杂度 / Time Complexity: O(n!)
空间复杂度 / Space Complexity: O(n)
📖 算法简介 / Introduction
回溯算法是一种通过枚举所有可能候选解来找到解的算法思想,采用递归方式构建解的候选集,遇到不满足条件时回退(撤销选择)继续搜索。
Backtracking is an algorithmic technique that finds all possible solutions by recursively building candidates and abandoning (“backtracking”) a candidate when it determines the partial candidate cannot lead to a valid solution.
💡 算法原理 / Principle
回溯算法的核心是”尝试”与”撤销”:
- 选择 (Choose):从候选集中选择一个可能的选项
- 探索 (Explore):递归进入下一层搜索
- 撤销 (Unchoose):回退并尝试下一个选项
核心思想:Systematically search for a solution by trying partial solutions and then abandoning them if they cannot lead to a valid complete solution.
🔑 关键概念 / Key Concepts
| 概念 | 说明 |
|---|---|
| 剪枝 (Pruning) | 提前排除不可能的分支,减少搜索空间 |
| 状态空间树 (State Space Tree) | 表示所有可能解的树结构 |
| 约束 (Constraint) | 问题的限制条件 |
📝 代码实现 / Implementation
# N-皇后问题示例
def solve_n_queens(n):
results = []
def is_valid(board, row, col):
# 检查列冲突
for i in range(row):
if board[i] == col:
return False
# 检查左上对角线
for i, j in zip(range(row-1, -1, -1), range(col-1, -1, -1)):
if board[i] == j:
return False
# 检查右上对角线
for i, j in zip(range(row-1, -1, -1), range(col+1, n)):
if board[i] == j:
return False
return True
def backtrack(row, board):
if row == n:
results.append(board[:])
return
for col in range(n):
if is_valid(board, row, col):
board[row] = col
backtrack(row + 1, board)
board[row] = -1 # 撤销选择
backtrack(0, [-1] * n)
return results
# 全排列示例
def permute(nums):
result = []
def backtrack(start):
if start == len(nums):
result.append(nums[:])
return
for i in range(start, len(nums)):
nums[start], nums[i] = nums[i], nums[start]
backtrack(start + 1)
nums[start], nums[i] = nums[i], nums[start] # 撤销
backtrack(0)
return result
✨ 示例 / Example
全排列:输入 [1,2,3]
输出:[[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]
子集:输入 [1,2,3]
输出:[[], [1], [2], [3], [1,2], [1,3], [2,3], [1,2,3]]
🎯 适用场景 / Scenarios
- 组合优化问题 — 如八皇后、数和谜题
- 排列组合生成 — 全排列、子集
- 迷宫求解 — 路径搜索
- 数独求解 — 约束满足问题
🔄 扩展阅读 / Further Reading
- 对比:回溯 vs 动态规划 — 两者都是分解问题,但回溯是穷举,DP是递推
- 剪枝优化 — 如何设计有效的剪枝条件
- 迭代加深搜索 — 适合有深度限制的问题
| *本文由 AI 自动生成 | Generated by AI* |