友情支持

如果您觉得这个笔记对您有所帮助,看在D瓜哥码这么多字的辛苦上,请友情支持一下,D瓜哥感激不尽,😜

支付宝

微信

有些打赏的朋友希望可以加个好友,欢迎关注D 瓜哥的微信公众号,这样就可以通过公众号的回复直接给我发信息。

wx jikerizhi

公众号的微信号是: jikerizhi因为众所周知的原因,有时图片加载不出来。 如果图片加载不出来可以直接通过搜索微信号来查找我的公众号。

Backtracking 回溯

首先介绍“回溯”算法的应用。“回溯”算法也叫“回溯搜索”算法,主要用于在一个庞大的空间里搜索我们所需要的问题的解。我们每天使用的“搜索引擎”就是帮助我们在庞大的互联网上搜索我们需要的信息。“搜索”引擎的“搜索”和“回溯搜索”算法的“搜索”意思是一样的。

“回溯”指的是“状态重置”,可以理解为“回到过去”、“恢复现场”,是在编码的过程中,是为了节约空间而使用的一种技巧。而回溯其实是“深度优先遍历”特有的一种现象。之所以是“深度优先遍历”,是因为我们要解决的问题通常是在一棵树上完成的,在这棵树上搜索需要的答案,一般使用深度优先遍历。

“全排列”就是一个非常经典的“回溯”算法的应用。我们知道,N 个数字的全排列一共有 N! 这么多个。

使用编程的方法得到全排列,就是在这样的一个树形结构中进行编程,具体来说,就是执行一次深度优先遍历,从树的根结点到叶子结点形成的路径就是一个全排列。

0046 01

说明:

  1. 每一个结点表示了“全排列”问题求解的不同阶段,这些阶段通过变量的“不同的值”体现;

  2. 这些变量的不同的值,也称之为“状态”;

  3. 使用深度优先遍历有“回头”的过程,在“回头”以后,状态变量需要设置成为和先前一样;

  4. 因此在回到上一层结点的过程中,需要撤销上一次选择,这个操作也称之为“状态重置”;

  5. 深度优先遍历,可以直接借助系统栈空间,为我们保存所需要的状态变量,在编码中只需要注意遍历到相应的结点的时候,状态变量的值是正确的,具体的做法是:往下走一层的时候,path 变量在尾部追加,而往回走的时候,需要撤销上一次的选择,也是在尾部操作,因此 path 变量是一个栈。

  6. 深度优先遍历通过“回溯”操作,实现了全局使用一份状态变量的效果。

解决一个回溯问题,实际上就是一个决策树的遍历过程。只需要思考 3 个问题:

  1. 路径:也就是已经做出的选择。

  2. 选择列表:也就是你当前可以做的选择。

  3. 结束条件:也就是到达决策树底层,无法再做选择的条件。

代码方面,回溯算法的框架:

result = []
def backtrack(路径, 选择列表):
    if 满足结束条件:
        result.add(路径)
        return

    for 选择 in 选择列表:
        做选择
        backtrack(路径, 选择列表)
        撤销选择

其核心就是 for 循环里面的递归,在递归调用之前「做选择」,在递归调用之后「撤销选择」,特别简单。

必须说明的是,不管怎么优化,都符合回溯框架,而且时间复杂度都不可能低于 O(N!),因为穷举整棵决策树是无法避免的。这也是回溯算法的一个特点,不像动态规划存在重叠子问题可以优化,回溯算法就是纯暴力穷举,复杂度一般都很高。

玩回溯,一定要画出递归调用树。

回溯优化,重要的是,要学会剪枝!

回溯三部曲:

  1. 定义递归函数以及参数

  2. 确定递归终止条件

  3. 思考递归单层搜索逻辑

经典题目

backtrack 01
  1. 17. Letter Combinations of a Phone Number

  2. 22. Generate Parentheses

  3. 37. 解数独

  4. 39. 组合总和

  5. 40. 组合总和 II

  6. 46. 全排列

  7. 47. Permutations II

  8. 51. N-Queens

  9. 52. N-Queens II

  10. 77. Combinations

  11. 78. Subsets

  12. 79. Word Search

  13. 89. Gray Code

  14. 90. 子集 II

  15. 93. 复原 IP 地址

  16. 95. Unique Binary Search Trees II

  17. 113. Path Sum II

  18. [0126-word-ladder-ii]

  19. 131. 分割回文串

  20. 140. 单词拆分 II

  21. [0212-word-search-ii]

  22. 216. 组合总和 III

  23. [0254-factor-combinations]

  24. 257. Binary Tree Paths

  25. [0267-palindrome-permutation-ii]

  26. [0282-expression-add-operators]

  27. [0291-word-pattern-ii]

  28. [0294-flip-game-ii]

  29. [0301-remove-invalid-parentheses]

  30. [0306-additive-number]

  31. [0320-generalized-abbreviation]

  32. [0351-android-unlock-patterns]

  33. [0357-count-numbers-with-unique-digits]

  34. [0401-binary-watch]

  35. [0411-minimum-unique-word-abbreviation]

  36. [0425-word-squares]

  37. [0465-optimal-account-balancing]

  38. [0473-matchsticks-to-square]

  39. [0489-robot-room-cleaner]

  40. [0491-non-decreasing-subsequences]

  41. 494. Target Sum

  42. [0526-beautiful-arrangement]

  43. [0638-shopping-offers]

  44. [0679-24-game]

  45. [0681-next-closest-time]

  46. [0691-stickers-to-spell-word]

  47. 698. Partition to K Equal Sum Subsets

  48. [0773-sliding-puzzle]

  49. [0784-letter-case-permutation]

  50. [0797-all-paths-from-source-to-target]

  51. [0816-ambiguous-coordinates]

  52. [0842-split-array-into-fibonacci-sequence]

  53. [0949-largest-time-for-given-digits]

  54. [0967-numbers-with-same-consecutive-differences]

  55. 980. 不同路径 III

  56. [0988-smallest-string-starting-from-leaf]

  57. [0996-number-of-squareful-arrays]

  58. [1066-campus-bikes-ii]

  59. [1079-letter-tile-possibilities]

  60. [1087-brace-expansion]

  61. [1088-confusing-number-ii]

  62. [1096-brace-expansion-ii]

  63. [1215-stepping-numbers]

  64. [1219-path-with-maximum-gold]

  65. [1238-circular-permutation-in-binary-representation]

  66. [1239-maximum-length-of-a-concatenated-string-with-unique-characters]

  67. [1240-tiling-a-rectangle-with-the-fewest-squares]

  68. [1255-maximum-score-words-formed-by-letters]

  69. [1258-synonymous-sentences]

  70. [1286-iterator-for-combination]

  71. [1307-verbal-arithmetic-puzzle]

  72. [1415-the-k-th-lexicographical-string-of-all-happy-strings-of-length-n]

  73. [1467-probability-of-a-two-boxes-having-the-same-number-of-distinct-balls]

  74. [1593-split-a-string-into-the-max-number-of-unique-substrings]

  75. [1601-maximum-number-of-achievable-transfer-requests]

  76. [1655-distribute-repeating-integers]

  77. [1718-construct-the-lexicographically-largest-valid-sequence]

  78. [1723-find-minimum-time-to-finish-all-jobs]

  79. [1774-closest-dessert-cost]

  80. [1799-maximize-score-after-n-operations]

  81. [1849-splitting-a-string-into-descending-consecutive-values]

  82. [1863-sum-of-all-subset-xor-totals]

  83. [1947-maximum-compatibility-score-sum]

  84. [1980-find-unique-binary-string]

  85. [1986-minimum-number-of-work-sessions-to-finish-the-tasks]

  86. [2002-maximum-product-of-the-length-of-two-palindromic-subsequences]

  87. [2014-longest-subsequence-repeated-k-times]

  88. [2044-count-number-of-maximum-bitwise-or-subsets]

  89. [2048-next-greater-numerically-balanced-number]

  90. [2056-number-of-valid-move-combinations-on-chessboard]

  91. [2065-maximum-path-quality-of-a-graph]

  92. [2151-maximum-good-people-based-on-statements]

  93. [2152-minimum-number-of-lines-to-cover-points]

  94. [2178-maximum-split-of-positive-even-integers]

  95. [2212-maximum-points-in-an-archery-competition]

  96. [2305-fair-distribution-of-cookies]

  97. [2375-construct-smallest-number-from-di-string]

  98. [2397-maximum-rows-covered-by-columns]

  99. [2597-the-number-of-beautiful-subsets]

  100. [2664-the-knights-tour]

  101. [2698-find-the-punishment-number-of-an-integer]

  102. [2708-maximum-strength-of-a-group]

  103. [2767-partition-string-into-minimum-beautiful-substrings]

  104. [2992-number-of-self-divisible-permutations]

  105. [3211-generate-binary-strings-without-adjacent-zeros]

  106. [3348-smallest-divisible-digit-product-ii]

  107. [3376-minimum-time-to-break-locks-i]

  108. [3437-permutations-iii]

附加题

  1. 写程序尝试生成递归调用树。