回溯分为组合篇排列篇分割篇子集篇

回溯具有高度模板化,以下为模版代码:

组合问题分为以下3种:

  • 1 数组中可选择的元素可以至多可以选择一次
    • 1 模版题;
    • 2 循环中的下一个迭代的起始索引+1
  • 2 数组中可选择的元素可以重复无限制选取
    • 1 在模版题的基础上;
    • 2 函数入口多增加越界判断(否则会无限循环)
    • 3 循环中的下一个迭代的起始索引不变。
  • 3 数组中可选择的元素可以至多先选择一次,同时返回结果没有重复子数组。
    • 1 在模版题目的基础上
    • 2 先对数组进行排序,使数组中重复元素挨着
    • 3 增加used数组进行去重,nums[i-1] = num[i]则说明重复(该重复为同层之间的重复,同一个树枝中允许重复)
    • // used[i - 1] == true,说明同一树枝candidates[i - 1]使用过
      // used[i - 1] == false,说明同一树层candidates[i - 1]使用过

1 组合问题

题目类型一。

给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。

你可以按 任何顺序 返回答案。

剪枝版本:

  • k – path.size(): 还需要加入的节点数量
  • n – (k – path.size()) + 1 : 下标需要在索引左边才能加入足够多的节点数量

2 组合总和

题目类型一。

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。

对于给定的输入,保证和为 target 的不同组合数少于 150 个。

1 模版题;

2 循环中的下一个迭代的起始索引+1

优化版本:

  • 1 candidates数组需要排序
  • 2 for循环中total+candidates <= target

3 组合总和III

题目类型二。

找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:

  • 只使用数字1到9
  • 每个数字 最多使用一次

返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。

题目类型二。

1 在模版题的基础上;

2 函数入口多增加越界判断(否则会无限循环)

3 循环中的下一个迭代的起始索引不变。

优化版本:

  • 1 数组需要排序(已经有序)
  • 2 for循环中total+candidates <= target

4 组合总和II

题目类型三。

给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用 一次 。

注意:解集不能包含重复的组合。

  • 1 在模版题目的基础上
  • 2 先对数组进行排序,使数组中重复元素挨着
  • 3 增加used数组进行去重,nums[i-1] = num[i]则说明重复(该重复为同层之间的重复,同一个树枝中允许重复)
  • // used[i - 1] == true,说明同一树枝candidates[i - 1]使用过
    // used[i - 1] == false,说明同一树层candidates[i - 1]使用过

直接给出优化版本。