回溯

描述

回溯其实就是暴力搜索,其思路是dfs。

回溯法思路的简单描述是:把问题的解空间转化成了图或者树的结构表示,然后使用**深度优先搜索策略**进行遍历,遍历的过程中记录和寻找所有可行解或者最优解。

分类

解空间树分为两种:**子集树和排列树**。两种在算法结构和思路上大体相同。

排列就是遍历所有空间,需要标记是否遍历过;for(i=0)

组合和子集其实是一类问题,只用遍历同一层还没遍历的,因此可以省去标记,for(i=start)

不同的是子集问题是,只要遍历一个点,就将当前符合要求的路径添加到最终答案中。

回溯法模板:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void backtrack(参数) {

    if (终止条件) {
        存放结果;
        return;
    }

//其实就是遍历与其相连的所有节点

    for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {

      判断是否处理过

        处理节点;

      记录状态、遍历过与否的标记

        backtrack(路径,选择列表); // 递归
        回溯,撤销处理结果,回退状态、遍历过与否的标记
    }
}

对于需要去重的回溯问题:

(1)排列:

for(int i = 0; i < nums.length; i++){

            //若在同一层已经遍历过(就是循环过了),则跳过这次

            if(i > 1 && nums[i] == nums[i-1] && !used[i - 1]) continue;

 

(2)子集和组合:

for(inti=start;i<nums.length;i++){

if(i>start&&nums[i]==nums[i-1])continue;

题目

当问题是要求满足某种性质(约束条件)的所有解或最优解时,往往使用回溯法。
它有“通用解题法”之美誉。

  1. 子集问题lc78,lc90
  2. 排列问题lc46,lc47
  3. 组合求和问题lc39,40,216
  4. 分割回文串lc131
  5. 阿里快递最短路alibaba(DFS)
  6. 组合问题lc77【lc77中有对回溯法的优化,即剪枝】,lc401
  7. 二维平面上使用回溯法 lc79
  8. floodfill lc200(岛屿的个数),130,417
  9. N皇后问题lc51
  10. 数独问题lc37
显示 Gitment 评论