From f4fc7a8eebdbe7701950de027536e141dea08660 Mon Sep 17 00:00:00 2001 From: krahets Date: Wed, 10 May 2023 19:38:29 +0800 Subject: [PATCH] deploy --- .../backtracking_algorithm/index.html | 782 +++++++++++------- .../permutations_ii.png | Bin 62284 -> 63341 bytes .../permutations_ii_pruning.png | Bin 80436 -> 81181 bytes .../permutations_ii_pruning_summary.png | Bin 74933 -> 76523 bytes .../permutations_problem/index.html | 18 +- search/search_index.json | 2 +- sitemap.xml | 114 +-- sitemap.xml.gz | Bin 716 -> 716 bytes 8 files changed, 555 insertions(+), 361 deletions(-) diff --git a/chapter_backtracking/backtracking_algorithm/index.html b/chapter_backtracking/backtracking_algorithm/index.html index 6f5eb6b55..f73c2fd08 100644 --- a/chapter_backtracking/backtracking_algorithm/index.html +++ b/chapter_backtracking/backtracking_algorithm/index.html @@ -2356,335 +2356,529 @@

13.1.4.   框架代码

回溯算法可用于解决许多搜索问题、约束满足问题和组合优化问题。为提升代码通用性,我们希望将回溯算法的“尝试、回退、剪枝”的主体框架提炼出来。

state 为问题的当前状态,choices 表示当前状态下可以做出的选择,则可得到以下回溯算法的框架代码。

-
def backtrack(state, choices, res):
-    """回溯算法框架"""
-    # 判断是否为解
-    if is_solution(state):
-        # 记录解
-        record_solution(state, res)
-        return
-    # 遍历所有选择
-    for choice in choices:
-        # 剪枝:判断选择是否合法
-        if is_valid(state, choice):
-            # 尝试:做出选择,更新状态
-            make_choice(state, choice)
-            backtrack(state, choices, res)
-            # 回退:撤销选择,恢复到之前的状态
-            undo_choice(state, choice)
-
-

下面,我们尝试基于此框架来解决例题三。在例题三中,状态 state 是节点遍历路径,选择 choices 是当前节点的左子节点和右子节点,结果 res 是路径列表,实现代码如下所示。

-
preorder_traversal_iii_template.java
/* 判断当前状态是否为解 */
-boolean isSolution(List<TreeNode> state) {
-    return !state.isEmpty() && state.get(state.size() - 1).val == 7;
-}
-
-/* 记录解 */
-void recordSolution(List<TreeNode> state, List<List<TreeNode>> res) {
-    res.add(new ArrayList<>(state));
-}
-
-/* 判断在当前状态下,该选择是否合法 */
-boolean isValid(List<TreeNode> state, TreeNode choice) {
-    return choice != null && choice.val != 3;
-}
-
-/* 更新状态 */
-void makeChoice(List<TreeNode> state, TreeNode choice) {
-    state.add(choice);
-}
-
-/* 恢复状态 */
-void undoChoice(List<TreeNode> state, TreeNode choice) {
-    state.remove(state.size() - 1);
-}
-
-/* 回溯算法:例题三 */
-void backtrack(List<TreeNode> state, List<TreeNode> choices, List<List<TreeNode>> res) {
-    // 检查是否为解
-    if (isSolution(state)) {
-        // 记录解
-        recordSolution(state, res);
-        return;
-    }
-    // 遍历所有选择
-    for (TreeNode choice : choices) {
-        // 剪枝:检查选择是否合法
-        if (isValid(state, choice)) {
-            // 尝试:做出选择,更新状态
-            makeChoice(state, choice);
-            // 进行下一轮选择
-            backtrack(state, Arrays.asList(choice.left, choice.right), res);
-            // 回退:撤销选择,恢复到之前的状态
-            undoChoice(state, choice);
-        }
-    }
-}
+
/* 回溯算法框架 */
+void backtrack(State state, List<Choice> choices, List<State> res) {
+    // 判断是否为解
+    if (isSolution(state)) {
+        // 记录解
+        recordSolution(state, res);
+        return;
+    }
+    // 遍历所有选择
+    for (Choice choice : choices) {
+        // 剪枝:判断选择是否合法
+        if (isValid(state, choice)) {
+            // 尝试:做出选择,更新状态
+            makeChoice(state, choice);
+            backtrack(state, choices, res);
+            // 回退:撤销选择,恢复到之前的状态
+            undoChoice(state, choice);
+        }
+    }
+}
 
-
preorder_traversal_iii_template.cpp
/* 判断当前状态是否为解 */
-bool isSolution(vector<TreeNode *> &state) {
-    return !state.empty() && state.back()->val == 7;
-}
-
-/* 记录解 */
-void recordSolution(vector<TreeNode *> &state, vector<vector<TreeNode *>> &res) {
-    res.push_back(state);
-}
-
-/* 判断在当前状态下,该选择是否合法 */
-bool isValid(vector<TreeNode *> &state, TreeNode *choice) {
-    return choice != nullptr && choice->val != 3;
-}
-
-/* 更新状态 */
-void makeChoice(vector<TreeNode *> &state, TreeNode *choice) {
-    state.push_back(choice);
-}
-
-/* 恢复状态 */
-void undoChoice(vector<TreeNode *> &state, TreeNode *choice) {
-    state.pop_back();
-}
-
-/* 回溯算法:例题三 */
-void backtrack(vector<TreeNode *> &state, vector<TreeNode *> &choices, vector<vector<TreeNode *>> &res) {
-    // 检查是否为解
-    if (isSolution(state)) {
-        // 记录解
-        recordSolution(state, res);
-        return;
-    }
-    // 遍历所有选择
-    for (TreeNode *choice : choices) {
-        // 剪枝:检查选择是否合法
-        if (isValid(state, choice)) {
-            // 尝试:做出选择,更新状态
-            makeChoice(state, choice);
-            // 进行下一轮选择
-            vector<TreeNode *> nextChoices{choice->left, choice->right};
-            backtrack(state, nextChoices, res);
-            // 回退:撤销选择,恢复到之前的状态
-            undoChoice(state, choice);
-        }
-    }
-}
+
/* 回溯算法框架 */
+void backtrack(State *state, vector<Choice *> &choices, vector<State *> &res) {
+    // 判断是否为解
+    if (isSolution(state)) {
+        // 记录解
+        recordSolution(state, res);
+        return;
+    }
+    // 遍历所有选择
+    for (Choice choice : choices) {
+        // 剪枝:判断选择是否合法
+        if (isValid(state, choice)) {
+            // 尝试:做出选择,更新状态
+            makeChoice(state, choice);
+            backtrack(state, choices, res);
+            // 回退:撤销选择,恢复到之前的状态
+            undoChoice(state, choice);
+        }
+    }
+}
 
-
preorder_traversal_iii_template.py
def is_solution(state: list[TreeNode]) -> bool:
-    """判断当前状态是否为解"""
-    return state and state[-1].val == 7
-
-def record_solution(state: list[TreeNode], res: list[list[TreeNode]]):
-    """记录解"""
-    res.append(list(state))
-
-def is_valid(state: list[TreeNode], choice: TreeNode) -> bool:
-    """判断在当前状态下,该选择是否合法"""
-    return choice is not None and choice.val != 3
-
-def make_choice(state: list[TreeNode], choice: TreeNode):
-    """更新状态"""
-    state.append(choice)
-
-def undo_choice(state: list[TreeNode], choice: TreeNode):
-    """恢复状态"""
-    state.pop()
-
-def backtrack(state: list[TreeNode], choices: list[TreeNode], res: list[list[TreeNode]]):
-    """回溯算法:例题三"""
-    # 检查是否为解
-    if is_solution(state):
-        # 记录解
-        record_solution(state, res)
-        return
-    # 遍历所有选择
-    for choice in choices:
-        # 剪枝:检查选择是否合法
-        if is_valid(state, choice):
-            # 尝试:做出选择,更新状态
-            make_choice(state, choice)
-            # 进行下一轮选择
-            backtrack(state, [choice.left, choice.right], res)
-            # 回退:撤销选择,恢复到之前的状态
-            undo_choice(state, choice)
+
def backtrack(state: State, choices: list[choice], res: list[state]) -> None:
+    """回溯算法框架"""
+    # 判断是否为解
+    if is_solution(state):
+        # 记录解
+        record_solution(state, res)
+        return
+    # 遍历所有选择
+    for choice in choices:
+        # 剪枝:判断选择是否合法
+        if is_valid(state, choice):
+            # 尝试:做出选择,更新状态
+            make_choice(state, choice)
+            backtrack(state, choices, res)
+            # 回退:撤销选择,恢复到之前的状态
+            undo_choice(state, choice)
 
-
preorder_traversal_iii_template.go
[class]{}-[func]{isSolution}
-
-[class]{}-[func]{recordSolution}
-
-[class]{}-[func]{isValid}
-
-[class]{}-[func]{makeChoice}
-
-[class]{}-[func]{undoChoice}
-
-[class]{}-[func]{backtrack}
+
/* 回溯算法框架 */
+func backtrack(state *State, choices []Choice, res *[]State) {
+    // 判断是否为解
+    if isSolution(state) {
+        // 记录解
+        recordSolution(state, res)
+        return
+    }
+    // 遍历所有选择
+    for _, choice := range choices {
+        // 剪枝:判断选择是否合法
+        if isValid(state, choice) {
+            // 尝试:做出选择,更新状态
+            makeChoice(state, choice)
+            backtrack(state, choices, res)
+            // 回退:撤销选择,恢复到之前的状态
+            undoChoice(state, choice)
+        }
+    }
+}
 
-
preorder_traversal_iii_template.js
[class]{}-[func]{isSolution}
-
-[class]{}-[func]{recordSolution}
-
-[class]{}-[func]{isValid}
-
-[class]{}-[func]{makeChoice}
-
-[class]{}-[func]{undoChoice}
-
-[class]{}-[func]{backtrack}
+
/* 回溯算法框架 */
+function backtrack(state, choices, res) {
+    // 判断是否为解
+    if (isSolution(state)) {
+        // 记录解
+        recordSolution(state, res);
+        return;
+    }
+    // 遍历所有选择
+    for (let choice of choices) {
+        // 剪枝:判断选择是否合法
+        if (isValid(state, choice)) {
+            // 尝试:做出选择,更新状态
+            makeChoice(state, choice);
+            backtrack(state, choices, res);
+            // 回退:撤销选择,恢复到之前的状态
+            undoChoice(state, choice);
+        }
+    }
+}
 
-
preorder_traversal_iii_template.ts
[class]{}-[func]{isSolution}
-
-[class]{}-[func]{recordSolution}
-
-[class]{}-[func]{isValid}
-
-[class]{}-[func]{makeChoice}
-
-[class]{}-[func]{undoChoice}
-
-[class]{}-[func]{backtrack}
+
/* 回溯算法框架 */
+function backtrack(state: State, choices: Choice[], res: State[]): void {
+    // 判断是否为解
+    if (isSolution(state)) {
+        // 记录解
+        recordSolution(state, res);
+        return;
+    }
+    // 遍历所有选择
+    for (let choice of choices) {
+        // 剪枝:判断选择是否合法
+        if (isValid(state, choice)) {
+            // 尝试:做出选择,更新状态
+            makeChoice(state, choice);
+            backtrack(state, choices, res);
+            // 回退:撤销选择,恢复到之前的状态
+            undoChoice(state, choice);
+        }
+    }
+}
 
-
preorder_traversal_iii_template.c
[class]{}-[func]{isSolution}
-
-[class]{}-[func]{recordSolution}
-
-[class]{}-[func]{isValid}
-
-[class]{}-[func]{makeChoice}
-
-[class]{}-[func]{undoChoice}
-
-[class]{}-[func]{backtrack}
+
/* 回溯算法框架 */
+void backtrack(State *state, Choice *choices, int numChoices, State *res, int numRes) {
+    // 判断是否为解
+    if (isSolution(state)) {
+        // 记录解
+        recordSolution(state, res, numRes);
+        return;
+    }
+    // 遍历所有选择
+    for (int i = 0; i < numChoices; i++) {
+        // 剪枝:判断选择是否合法
+        if (isValid(state, &choices[i])) {
+            // 尝试:做出选择,更新状态
+            makeChoice(state, &choices[i]);
+            backtrack(state, choices, numChoices, res, numRes);
+            // 回退:撤销选择,恢复到之前的状态
+            undoChoice(state, &choices[i]);
+        }
+    }
+}
 
-
preorder_traversal_iii_template.cs
/* 判断当前状态是否为解 */
-bool isSolution(List<TreeNode> state) {
-    return state.Count != 0 && state[^1].val == 7;
-}
-
-/* 记录解 */
-void recordSolution(List<TreeNode> state, List<List<TreeNode>> res) {
-    res.Add(new List<TreeNode>(state));
-}
-
-/* 判断在当前状态下,该选择是否合法 */
-bool isValid(List<TreeNode> state, TreeNode choice) {
-    return choice != null && choice.val != 3;
-}
-
-/* 更新状态 */
-void makeChoice(List<TreeNode> state, TreeNode choice) {
-    state.Add(choice);
-}
-
-/* 恢复状态 */
-void undoChoice(List<TreeNode> state, TreeNode choice) {
-    state.RemoveAt(state.Count - 1);
-}
-
-/* 回溯算法:例题三 */
-void backtrack(List<TreeNode> state, List<TreeNode> choices, List<List<TreeNode>> res) {
-    // 检查是否为解
-    if (isSolution(state)) {
-        // 记录解
-        recordSolution(state, res);
-        return;
-    }
-    // 遍历所有选择
-    foreach (TreeNode choice in choices) {
-        // 剪枝:检查选择是否合法
-        if (isValid(state, choice)) {
-            // 尝试:做出选择,更新状态
-            makeChoice(state, choice);
-            // 进行下一轮选择
-            backtrack(state, new List<TreeNode> { choice.left, choice.right }, res);
-            // 回退:撤销选择,恢复到之前的状态
-            undoChoice(state, choice);
-        }
-    }
-}
+
/* 回溯算法框架 */
+void backtrack(State state, List<Choice> choices, List<State> res) {
+    // 判断是否为解
+    if (isSolution(state)) {
+        // 记录解
+        recordSolution(state, res);
+        return;
+    }
+    // 遍历所有选择
+    foreach (Choice choice in choices) {
+        // 剪枝:判断选择是否合法
+        if (isValid(state, choice)) {
+            // 尝试:做出选择,更新状态
+            makeChoice(state, choice);
+            backtrack(state, choices, res);
+            // 回退:撤销选择,恢复到之前的状态
+            undoChoice(state, choice);
+        }
+    }
+}
 
-
preorder_traversal_iii_template.swift
/* 判断当前状态是否为解 */
-func isSolution(state: [TreeNode]) -> Bool {
-    !state.isEmpty && state.last!.val == 7
-}
-
-/* 记录解 */
-func recordSolution(state: [TreeNode], res: inout [[TreeNode]]) {
-    res.append(state)
-}
-
-/* 判断在当前状态下,该选择是否合法 */
-func isValid(state: [TreeNode], choice: TreeNode?) -> Bool {
-    choice != nil && choice!.val != 3
-}
-
-/* 更新状态 */
-func makeChoice(state: inout [TreeNode], choice: TreeNode) {
-    state.append(choice)
-}
-
-/* 恢复状态 */
-func undoChoice(state: inout [TreeNode], choice: TreeNode) {
-    state.removeLast()
-}
-
-/* 回溯算法:例题三 */
-func backtrack(state: inout [TreeNode], choices: [TreeNode], res: inout [[TreeNode]]) {
-    // 检查是否为解
-    if isSolution(state: state) {
-        recordSolution(state: state, res: &res)
-        return
-    }
-    // 遍历所有选择
-    for choice in choices {
-        // 剪枝:检查选择是否合法
-        if isValid(state: state, choice: choice) {
-            // 尝试:做出选择,更新状态
-            makeChoice(state: &state, choice: choice)
-            // 进行下一轮选择
-            backtrack(state: &state, choices: [choice.left, choice.right].compactMap { $0 }, res: &res)
-            // 回退:撤销选择,恢复到之前的状态
-            undoChoice(state: &state, choice: choice)
-        }
-    }
-}
+
/* 回溯算法框架 */
+func backtrack(state: inout State, choices: [Choice], res: inout [State]) {
+    // 判断是否为解
+    if isSolution(state: state) {
+        // 记录解
+        recordSolution(state: state, res: &res)
+        return
+    }
+    // 遍历所有选择
+    for choice in choices {
+        // 剪枝:判断选择是否合法
+        if isValid(state: state, choice: choice) {
+            // 尝试:做出选择,更新状态
+            makeChoice(state: &state, choice: choice)
+            backtrack(state: &state, choices: choices, res: &res)
+            // 回退:撤销选择,恢复到之前的状态
+            undoChoice(state: &state, choice: choice)
+        }
+    }
+}
 
-
preorder_traversal_iii_template.zig
[class]{}-[func]{isSolution}
-
-[class]{}-[func]{recordSolution}
-
-[class]{}-[func]{isValid}
-
-[class]{}-[func]{makeChoice}
-
-[class]{}-[func]{undoChoice}
+

+
+
+
+
+

下面,我们尝试基于此框架来解决例题三。在例题三中,状态 state 是节点遍历路径,选择 choices 是当前节点的左子节点和右子节点,结果 res 是路径列表,实现代码如下所示。

+
+
+
+
preorder_traversal_iii_template.java
/* 判断当前状态是否为解 */
+boolean isSolution(List<TreeNode> state) {
+    return !state.isEmpty() && state.get(state.size() - 1).val == 7;
+}
+
+/* 记录解 */
+void recordSolution(List<TreeNode> state, List<List<TreeNode>> res) {
+    res.add(new ArrayList<>(state));
+}
 
-[class]{}-[func]{backtrack}
+/* 判断在当前状态下,该选择是否合法 */
+boolean isValid(List<TreeNode> state, TreeNode choice) {
+    return choice != null && choice.val != 3;
+}
+
+/* 更新状态 */
+void makeChoice(List<TreeNode> state, TreeNode choice) {
+    state.add(choice);
+}
+
+/* 恢复状态 */
+void undoChoice(List<TreeNode> state, TreeNode choice) {
+    state.remove(state.size() - 1);
+}
+
+/* 回溯算法:例题三 */
+void backtrack(List<TreeNode> state, List<TreeNode> choices, List<List<TreeNode>> res) {
+    // 检查是否为解
+    if (isSolution(state)) {
+        // 记录解
+        recordSolution(state, res);
+        return;
+    }
+    // 遍历所有选择
+    for (TreeNode choice : choices) {
+        // 剪枝:检查选择是否合法
+        if (isValid(state, choice)) {
+            // 尝试:做出选择,更新状态
+            makeChoice(state, choice);
+            // 进行下一轮选择
+            backtrack(state, Arrays.asList(choice.left, choice.right), res);
+            // 回退:撤销选择,恢复到之前的状态
+            undoChoice(state, choice);
+        }
+    }
+}
+
+
+
+
preorder_traversal_iii_template.cpp
/* 判断当前状态是否为解 */
+bool isSolution(vector<TreeNode *> &state) {
+    return !state.empty() && state.back()->val == 7;
+}
+
+/* 记录解 */
+void recordSolution(vector<TreeNode *> &state, vector<vector<TreeNode *>> &res) {
+    res.push_back(state);
+}
+
+/* 判断在当前状态下,该选择是否合法 */
+bool isValid(vector<TreeNode *> &state, TreeNode *choice) {
+    return choice != nullptr && choice->val != 3;
+}
+
+/* 更新状态 */
+void makeChoice(vector<TreeNode *> &state, TreeNode *choice) {
+    state.push_back(choice);
+}
+
+/* 恢复状态 */
+void undoChoice(vector<TreeNode *> &state, TreeNode *choice) {
+    state.pop_back();
+}
+
+/* 回溯算法:例题三 */
+void backtrack(vector<TreeNode *> &state, vector<TreeNode *> &choices, vector<vector<TreeNode *>> &res) {
+    // 检查是否为解
+    if (isSolution(state)) {
+        // 记录解
+        recordSolution(state, res);
+        return;
+    }
+    // 遍历所有选择
+    for (TreeNode *choice : choices) {
+        // 剪枝:检查选择是否合法
+        if (isValid(state, choice)) {
+            // 尝试:做出选择,更新状态
+            makeChoice(state, choice);
+            // 进行下一轮选择
+            vector<TreeNode *> nextChoices{choice->left, choice->right};
+            backtrack(state, nextChoices, res);
+            // 回退:撤销选择,恢复到之前的状态
+            undoChoice(state, choice);
+        }
+    }
+}
+
+
+
+
preorder_traversal_iii_template.py
def is_solution(state: list[TreeNode]) -> bool:
+    """判断当前状态是否为解"""
+    return state and state[-1].val == 7
+
+def record_solution(state: list[TreeNode], res: list[list[TreeNode]]):
+    """记录解"""
+    res.append(list(state))
+
+def is_valid(state: list[TreeNode], choice: TreeNode) -> bool:
+    """判断在当前状态下,该选择是否合法"""
+    return choice is not None and choice.val != 3
+
+def make_choice(state: list[TreeNode], choice: TreeNode):
+    """更新状态"""
+    state.append(choice)
+
+def undo_choice(state: list[TreeNode], choice: TreeNode):
+    """恢复状态"""
+    state.pop()
+
+def backtrack(state: list[TreeNode], choices: list[TreeNode], res: list[list[TreeNode]]):
+    """回溯算法:例题三"""
+    # 检查是否为解
+    if is_solution(state):
+        # 记录解
+        record_solution(state, res)
+        return
+    # 遍历所有选择
+    for choice in choices:
+        # 剪枝:检查选择是否合法
+        if is_valid(state, choice):
+            # 尝试:做出选择,更新状态
+            make_choice(state, choice)
+            # 进行下一轮选择
+            backtrack(state, [choice.left, choice.right], res)
+            # 回退:撤销选择,恢复到之前的状态
+            undo_choice(state, choice)
+
+
+
+
preorder_traversal_iii_template.go
[class]{}-[func]{isSolution}
+
+[class]{}-[func]{recordSolution}
+
+[class]{}-[func]{isValid}
+
+[class]{}-[func]{makeChoice}
+
+[class]{}-[func]{undoChoice}
+
+[class]{}-[func]{backtrack}
+
+
+
+
preorder_traversal_iii_template.js
[class]{}-[func]{isSolution}
+
+[class]{}-[func]{recordSolution}
+
+[class]{}-[func]{isValid}
+
+[class]{}-[func]{makeChoice}
+
+[class]{}-[func]{undoChoice}
+
+[class]{}-[func]{backtrack}
+
+
+
+
preorder_traversal_iii_template.ts
[class]{}-[func]{isSolution}
+
+[class]{}-[func]{recordSolution}
+
+[class]{}-[func]{isValid}
+
+[class]{}-[func]{makeChoice}
+
+[class]{}-[func]{undoChoice}
+
+[class]{}-[func]{backtrack}
+
+
+
+
preorder_traversal_iii_template.c
[class]{}-[func]{isSolution}
+
+[class]{}-[func]{recordSolution}
+
+[class]{}-[func]{isValid}
+
+[class]{}-[func]{makeChoice}
+
+[class]{}-[func]{undoChoice}
+
+[class]{}-[func]{backtrack}
+
+
+
+
preorder_traversal_iii_template.cs
/* 判断当前状态是否为解 */
+bool isSolution(List<TreeNode> state) {
+    return state.Count != 0 && state[^1].val == 7;
+}
+
+/* 记录解 */
+void recordSolution(List<TreeNode> state, List<List<TreeNode>> res) {
+    res.Add(new List<TreeNode>(state));
+}
+
+/* 判断在当前状态下,该选择是否合法 */
+bool isValid(List<TreeNode> state, TreeNode choice) {
+    return choice != null && choice.val != 3;
+}
+
+/* 更新状态 */
+void makeChoice(List<TreeNode> state, TreeNode choice) {
+    state.Add(choice);
+}
+
+/* 恢复状态 */
+void undoChoice(List<TreeNode> state, TreeNode choice) {
+    state.RemoveAt(state.Count - 1);
+}
+
+/* 回溯算法:例题三 */
+void backtrack(List<TreeNode> state, List<TreeNode> choices, List<List<TreeNode>> res) {
+    // 检查是否为解
+    if (isSolution(state)) {
+        // 记录解
+        recordSolution(state, res);
+        return;
+    }
+    // 遍历所有选择
+    foreach (TreeNode choice in choices) {
+        // 剪枝:检查选择是否合法
+        if (isValid(state, choice)) {
+            // 尝试:做出选择,更新状态
+            makeChoice(state, choice);
+            // 进行下一轮选择
+            backtrack(state, new List<TreeNode> { choice.left, choice.right }, res);
+            // 回退:撤销选择,恢复到之前的状态
+            undoChoice(state, choice);
+        }
+    }
+}
+
+
+
+
preorder_traversal_iii_template.swift
/* 判断当前状态是否为解 */
+func isSolution(state: [TreeNode]) -> Bool {
+    !state.isEmpty && state.last!.val == 7
+}
+
+/* 记录解 */
+func recordSolution(state: [TreeNode], res: inout [[TreeNode]]) {
+    res.append(state)
+}
+
+/* 判断在当前状态下,该选择是否合法 */
+func isValid(state: [TreeNode], choice: TreeNode?) -> Bool {
+    choice != nil && choice!.val != 3
+}
+
+/* 更新状态 */
+func makeChoice(state: inout [TreeNode], choice: TreeNode) {
+    state.append(choice)
+}
+
+/* 恢复状态 */
+func undoChoice(state: inout [TreeNode], choice: TreeNode) {
+    state.removeLast()
+}
+
+/* 回溯算法:例题三 */
+func backtrack(state: inout [TreeNode], choices: [TreeNode], res: inout [[TreeNode]]) {
+    // 检查是否为解
+    if isSolution(state: state) {
+        recordSolution(state: state, res: &res)
+        return
+    }
+    // 遍历所有选择
+    for choice in choices {
+        // 剪枝:检查选择是否合法
+        if isValid(state: state, choice: choice) {
+            // 尝试:做出选择,更新状态
+            makeChoice(state: &state, choice: choice)
+            // 进行下一轮选择
+            backtrack(state: &state, choices: [choice.left, choice.right].compactMap { $0 }, res: &res)
+            // 回退:撤销选择,恢复到之前的状态
+            undoChoice(state: &state, choice: choice)
+        }
+    }
+}
+
+
+
+
preorder_traversal_iii_template.zig
[class]{}-[func]{isSolution}
+
+[class]{}-[func]{recordSolution}
+
+[class]{}-[func]{isValid}
+
+[class]{}-[func]{makeChoice}
+
+[class]{}-[func]{undoChoice}
+
+[class]{}-[func]{backtrack}
 
-

相较于基于前序遍历的实现代码,基于回溯算法框架的实现代码虽然显得啰嗦,但通用性更好,适用于各种不同的回溯算法问题。实际上,所有回溯问题都可以在该框架下解决。我们只需要根据问题特点来定义框架中的各个变量,实现各个方法即可。

+

相较于基于前序遍历的实现代码,基于回溯算法框架的实现代码虽然显得啰嗦,但通用性更好。实际上,所有回溯问题都可以在该框架下解决。我们需要根据具体问题来定义 statechoices ,并实现框架中的各个方法。

13.1.5.   典型例题

搜索问题:这类问题的目标是找到满足特定条件的解决方案。