回溯算法 (Backtracking)

🧮 回溯算法 (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

回溯算法的核心是”尝试”与”撤销”:

  1. 选择 (Choose):从候选集中选择一个可能的选项
  2. 探索 (Explore):递归进入下一层搜索
  3. 撤销 (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*