This commit is contained in:
krahets
2025-04-27 16:54:37 +08:00
parent 11781447e8
commit 5817118a68
38 changed files with 127 additions and 127 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -4393,7 +4393,7 @@
<p align="center"> 图 7-4 &nbsp; 完美二叉树 </p>
<h3 id="2_1">2. &nbsp; 完全二叉树<a class="headerlink" href="#2_1" title="Permanent link">&para;</a></h3>
<p>如图 7-5 所示,<u>完全二叉树(complete binary tree</u>只有最底层的节点未被填满,且最底层节点尽量靠左填充。请注意,完美二叉树也是一棵完全二叉树。</p>
<p>如图 7-5 所示,<u>完全二叉树(complete binary tree</u>仅允许最底层的节点不完全填满,且最底层节点必须从左至右依次连续填充。请注意,完美二叉树也是一棵完全二叉树。</p>
<p><a class="glightbox" href="../binary_tree.assets/complete_binary_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="完全二叉树" class="animation-figure" src="../binary_tree.assets/complete_binary_tree.png" /></a></p>
<p align="center"> 图 7-5 &nbsp; 完全二叉树 </p>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -2798,18 +2798,18 @@
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#1311-trying-and-retreating" class="md-nav__link">
<a href="#1311-trial-and-retreat" class="md-nav__link">
<span class="md-ellipsis">
13.1.1 &nbsp; Trying and retreating
13.1.1 &nbsp; Trial and retreat
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#1312-pruning" class="md-nav__link">
<a href="#1312-prune" class="md-nav__link">
<span class="md-ellipsis">
13.1.2 &nbsp; Pruning
13.1.2 &nbsp; Prune
</span>
</a>
@@ -3566,18 +3566,18 @@
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#1311-trying-and-retreating" class="md-nav__link">
<a href="#1311-trial-and-retreat" class="md-nav__link">
<span class="md-ellipsis">
13.1.1 &nbsp; Trying and retreating
13.1.1 &nbsp; Trial and retreat
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#1312-pruning" class="md-nav__link">
<a href="#1312-prune" class="md-nav__link">
<span class="md-ellipsis">
13.1.2 &nbsp; Pruning
13.1.2 &nbsp; Prune
</span>
</a>
@@ -3656,13 +3656,13 @@
<!-- Page content -->
<h1 id="131-backtracking-algorithms">13.1 &nbsp; Backtracking algorithms<a class="headerlink" href="#131-backtracking-algorithms" title="Permanent link">&para;</a></h1>
<p><u>Backtracking algorithm</u> is a method to solve problems by exhaustive search, where the core idea is to start from an initial state and brute force all possible solutions, recording the correct ones until a solution is found or all possible choices are exhausted without finding a solution.</p>
<p>Backtracking typically employs "depth-first search" to traverse the solution space. In the "Binary Tree" chapter, we mentioned that pre-order, in-order, and post-order traversals are all depth-first searches. Next, we use pre-order traversal to construct a backtracking problem to gradually understand the workings of the backtracking algorithm.</p>
<p><u>Backtracking algorithm</u> is a method to solve problems by exhaustive search. Its core concept is to start from an initial state and brutally search for all possible solutions. The algorithm records the correct ones until a solution is found or all possible solutions have been tried but no solution can be found.</p>
<p>Backtracking typically employs "depth-first search" to traverse the solution space. In the "Binary tree" chapter, we mentioned that pre-order, in-order, and post-order traversals are all depth-first searches. Next, we are going to use pre-order traversal to solve a backtracking problem. This helps us to understand how the algorithm works gradually.</p>
<div class="admonition question">
<p class="admonition-title">Example One</p>
<p>Given a binary tree, search and record all nodes with a value of <span class="arithmatex">\(7\)</span>, please return a list of nodes.</p>
<p>Given a binary tree, search and record all nodes with a value of <span class="arithmatex">\(7\)</span> and return them in a list.</p>
</div>
<p>For this problem, we traverse this tree in pre-order and check if the current node's value is <span class="arithmatex">\(7\)</span>. If it is, we add the node's value to the result list <code>res</code>. The relevant process is shown in Figure 13-1:</p>
<p>To solve this problem, we traverse this tree in pre-order and check if the current node's value is <span class="arithmatex">\(7\)</span>. If it is, we add the node's value to the result list <code>res</code>. The process is shown in Figure 13-1:</p>
<div class="tabbed-set tabbed-alternate" data-tabs="1:14"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><input id="__tabbed_1_3" name="__tabbed_1" type="radio" /><input id="__tabbed_1_4" name="__tabbed_1" type="radio" /><input id="__tabbed_1_5" name="__tabbed_1" type="radio" /><input id="__tabbed_1_6" name="__tabbed_1" type="radio" /><input id="__tabbed_1_7" name="__tabbed_1" type="radio" /><input id="__tabbed_1_8" name="__tabbed_1" type="radio" /><input id="__tabbed_1_9" name="__tabbed_1" type="radio" /><input id="__tabbed_1_10" name="__tabbed_1" type="radio" /><input id="__tabbed_1_11" name="__tabbed_1" type="radio" /><input id="__tabbed_1_12" name="__tabbed_1" type="radio" /><input id="__tabbed_1_13" name="__tabbed_1" type="radio" /><input id="__tabbed_1_14" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">Python</label><label for="__tabbed_1_2">C++</label><label for="__tabbed_1_3">Java</label><label for="__tabbed_1_4">C#</label><label for="__tabbed_1_5">Go</label><label for="__tabbed_1_6">Swift</label><label for="__tabbed_1_7">JS</label><label for="__tabbed_1_8">TS</label><label for="__tabbed_1_9">Dart</label><label for="__tabbed_1_10">Rust</label><label for="__tabbed_1_11">C</label><label for="__tabbed_1_12">Kotlin</label><label for="__tabbed_1_13">Ruby</label><label for="__tabbed_1_14">Zig</label></div>
<div class="tabbed-content">
<div class="tabbed-block">
@@ -3756,15 +3756,15 @@
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_nodes.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="Searching nodes in pre-order traversal" class="animation-figure" src="../backtracking_algorithm.assets/preorder_find_nodes.png" /></a></p>
<p align="center"> Figure 13-1 &nbsp; Searching nodes in pre-order traversal </p>
<h2 id="1311-trying-and-retreating">13.1.1 &nbsp; Trying and retreating<a class="headerlink" href="#1311-trying-and-retreating" title="Permanent link">&para;</a></h2>
<p><strong>The reason it is called backtracking is that the algorithm uses a "try" and "retreat" strategy when searching the solution space</strong>. When the algorithm encounters a state where it can no longer progress or fails to achieve a satisfying solution, it undoes the previous choice, reverts to the previous state, and tries other possible choices.</p>
<p>For Example One, visiting each node represents a "try", and passing a leaf node or returning to the parent node's <code>return</code> represents "retreat".</p>
<p>It's worth noting that <strong>retreat is not merely about function returns</strong>. We expand slightly on Example One for clarification.</p>
<h2 id="1311-trial-and-retreat">13.1.1 &nbsp; Trial and retreat<a class="headerlink" href="#1311-trial-and-retreat" title="Permanent link">&para;</a></h2>
<p><strong>It is called a backtracking algorithm because it uses a "trial" and "retreat" strategy when searching the solution space</strong>. During the search, whenever it encounters a state where it can no longer proceed to obtain a satisfying solution, it undoes the previous choice and reverts to the previous state so that other possible choices can be chosen for the next attempt.</p>
<p>In Example One, visiting each node starts a "trial". And passing a leaf node or the <code>return</code> statement to going back to the parent node suggests "retreat".</p>
<p>It's worth noting that <strong>retreat is not merely about function returns</strong>. We'll expand slightly on Example One question to explain what it means.</p>
<div class="admonition question">
<p class="admonition-title">Example Two</p>
<p>In a binary tree, search for all nodes with a value of <span class="arithmatex">\(7\)</span> and <strong>please return the paths from the root node to these nodes</strong>.</p>
<p>In a binary tree, search for all nodes with a value of <span class="arithmatex">\(7\)</span> and for all matching nodes, <strong>please return the paths from the root node to that node</strong>.</p>
</div>
<p>Based on the code from Example One, we need to use a list <code>path</code> to record the visited node paths. When a node with a value of <span class="arithmatex">\(7\)</span> is reached, we copy <code>path</code> and add it to the result list <code>res</code>. After the traversal, <code>res</code> holds all the solutions. The code is as shown:</p>
<p>Based on the code from Example One, we need to use a list called <code>path</code> to record the visited node paths. When a node with a value of <span class="arithmatex">\(7\)</span> is reached, we copy <code>path</code> and add it to the result list <code>res</code>. After the traversal, <code>res</code> holds all the solutions. The code is as shown:</p>
<div class="tabbed-set tabbed-alternate" data-tabs="2:14"><input checked="checked" id="__tabbed_2_1" name="__tabbed_2" type="radio" /><input id="__tabbed_2_2" name="__tabbed_2" type="radio" /><input id="__tabbed_2_3" name="__tabbed_2" type="radio" /><input id="__tabbed_2_4" name="__tabbed_2" type="radio" /><input id="__tabbed_2_5" name="__tabbed_2" type="radio" /><input id="__tabbed_2_6" name="__tabbed_2" type="radio" /><input id="__tabbed_2_7" name="__tabbed_2" type="radio" /><input id="__tabbed_2_8" name="__tabbed_2" type="radio" /><input id="__tabbed_2_9" name="__tabbed_2" type="radio" /><input id="__tabbed_2_10" name="__tabbed_2" type="radio" /><input id="__tabbed_2_11" name="__tabbed_2" type="radio" /><input id="__tabbed_2_12" name="__tabbed_2" type="radio" /><input id="__tabbed_2_13" name="__tabbed_2" type="radio" /><input id="__tabbed_2_14" name="__tabbed_2" type="radio" /><div class="tabbed-labels"><label for="__tabbed_2_1">Python</label><label for="__tabbed_2_2">C++</label><label for="__tabbed_2_3">Java</label><label for="__tabbed_2_4">C#</label><label for="__tabbed_2_5">Go</label><label for="__tabbed_2_6">Swift</label><label for="__tabbed_2_7">JS</label><label for="__tabbed_2_8">TS</label><label for="__tabbed_2_9">Dart</label><label for="__tabbed_2_10">Rust</label><label for="__tabbed_2_11">C</label><label for="__tabbed_2_12">Kotlin</label><label for="__tabbed_2_13">Ruby</label><label for="__tabbed_2_14">Zig</label></div>
<div class="tabbed-content">
<div class="tabbed-block">
@@ -3867,8 +3867,8 @@
</div>
</div>
</div>
<p>In each "try", we record the path by adding the current node to <code>path</code>; before "retreating", we need to pop the node from <code>path</code> <strong>to restore the state before this attempt</strong>.</p>
<p>Observe the process shown in Figure 13-2, <strong>we can understand trying and retreating as "advancing" and "undoing"</strong>, two operations that are reverse to each other.</p>
<p>In each "trial", we record the path by adding the current node to <code>path</code>. Whenever we need to "retreat", we pop the node from <code>path</code> <strong>to restore the state prior to this failed attempt</strong>.</p>
<p>By observing the process shown in Figure 13-2, <strong>the trial is like "advancing", and retreat is like "undoing"</strong>. The later pairs can be seen as a reverse operation to their counterpart.</p>
<div class="tabbed-set tabbed-alternate" data-tabs="3:11"><input checked="checked" id="__tabbed_3_1" name="__tabbed_3" type="radio" /><input id="__tabbed_3_2" name="__tabbed_3" type="radio" /><input id="__tabbed_3_3" name="__tabbed_3" type="radio" /><input id="__tabbed_3_4" name="__tabbed_3" type="radio" /><input id="__tabbed_3_5" name="__tabbed_3" type="radio" /><input id="__tabbed_3_6" name="__tabbed_3" type="radio" /><input id="__tabbed_3_7" name="__tabbed_3" type="radio" /><input id="__tabbed_3_8" name="__tabbed_3" type="radio" /><input id="__tabbed_3_9" name="__tabbed_3" type="radio" /><input id="__tabbed_3_10" name="__tabbed_3" type="radio" /><input id="__tabbed_3_11" name="__tabbed_3" type="radio" /><div class="tabbed-labels"><label for="__tabbed_3_1">&lt;1&gt;</label><label for="__tabbed_3_2">&lt;2&gt;</label><label for="__tabbed_3_3">&lt;3&gt;</label><label for="__tabbed_3_4">&lt;4&gt;</label><label for="__tabbed_3_5">&lt;5&gt;</label><label for="__tabbed_3_6">&lt;6&gt;</label><label for="__tabbed_3_7">&lt;7&gt;</label><label for="__tabbed_3_8">&lt;8&gt;</label><label for="__tabbed_3_9">&lt;9&gt;</label><label for="__tabbed_3_10">&lt;10&gt;</label><label for="__tabbed_3_11">&lt;11&gt;</label></div>
<div class="tabbed-content">
<div class="tabbed-block">
@@ -3908,13 +3908,13 @@
</div>
<p align="center"> Figure 13-2 &nbsp; Trying and retreating </p>
<h2 id="1312-pruning">13.1.2 &nbsp; Pruning<a class="headerlink" href="#1312-pruning" title="Permanent link">&para;</a></h2>
<h2 id="1312-prune">13.1.2 &nbsp; Prune<a class="headerlink" href="#1312-prune" title="Permanent link">&para;</a></h2>
<p>Complex backtracking problems usually involve one or more constraints, <strong>which are often used for "pruning"</strong>.</p>
<div class="admonition question">
<p class="admonition-title">Example Three</p>
<p>In a binary tree, search for all nodes with a value of <span class="arithmatex">\(7\)</span> and return the paths from the root to these nodes, <strong>requiring that the paths do not contain nodes with a value of <span class="arithmatex">\(3\)</span></strong>.</p>
<p>In a binary tree, search for all nodes with a value of <span class="arithmatex">\(7\)</span> and return the paths from the root to these nodes, <strong>with restriction that the paths do not contain nodes with a value of <span class="arithmatex">\(3\)</span></strong>.</p>
</div>
<p>To meet the above constraints, <strong>we need to add a pruning operation</strong>: during the search process, if a node with a value of <span class="arithmatex">\(3\)</span> is encountered, it returns early, discontinuing further search. The code is as shown:</p>
<p>To meet the above constraints, <strong>we need to add a pruning operation</strong>: during the search process, if a node with a value of <span class="arithmatex">\(3\)</span> is encountered, it aborts further searching down through the path immediately. The code is as shown:</p>
<div class="tabbed-set tabbed-alternate" data-tabs="4:14"><input checked="checked" id="__tabbed_4_1" name="__tabbed_4" type="radio" /><input id="__tabbed_4_2" name="__tabbed_4" type="radio" /><input id="__tabbed_4_3" name="__tabbed_4" type="radio" /><input id="__tabbed_4_4" name="__tabbed_4" type="radio" /><input id="__tabbed_4_5" name="__tabbed_4" type="radio" /><input id="__tabbed_4_6" name="__tabbed_4" type="radio" /><input id="__tabbed_4_7" name="__tabbed_4" type="radio" /><input id="__tabbed_4_8" name="__tabbed_4" type="radio" /><input id="__tabbed_4_9" name="__tabbed_4" type="radio" /><input id="__tabbed_4_10" name="__tabbed_4" type="radio" /><input id="__tabbed_4_11" name="__tabbed_4" type="radio" /><input id="__tabbed_4_12" name="__tabbed_4" type="radio" /><input id="__tabbed_4_13" name="__tabbed_4" type="radio" /><input id="__tabbed_4_14" name="__tabbed_4" type="radio" /><div class="tabbed-labels"><label for="__tabbed_4_1">Python</label><label for="__tabbed_4_2">C++</label><label for="__tabbed_4_3">Java</label><label for="__tabbed_4_4">C#</label><label for="__tabbed_4_5">Go</label><label for="__tabbed_4_6">Swift</label><label for="__tabbed_4_7">JS</label><label for="__tabbed_4_8">TS</label><label for="__tabbed_4_9">Dart</label><label for="__tabbed_4_10">Rust</label><label for="__tabbed_4_11">C</label><label for="__tabbed_4_12">Kotlin</label><label for="__tabbed_4_13">Ruby</label><label for="__tabbed_4_14">Zig</label></div>
<div class="tabbed-content">
<div class="tabbed-block">
@@ -4020,12 +4020,12 @@
</div>
</div>
</div>
<p>"Pruning" is a very vivid noun. As shown in Figure 13-3, in the search process, <strong>we "cut off" the search branches that do not meet the constraints</strong>, avoiding many meaningless attempts, thus enhancing the search efficiency.</p>
<p>"Pruning" is a very vivid noun. As shown in Figure 13-3, in the search process, <strong>we "cut off" the search branches that do not meet the constraints</strong>. It avoids further unnecessary attempts, thus enhances the search efficiency.</p>
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_constrained_paths.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="Pruning based on constraints" class="animation-figure" src="../backtracking_algorithm.assets/preorder_find_constrained_paths.png" /></a></p>
<p align="center"> Figure 13-3 &nbsp; Pruning based on constraints </p>
<h2 id="1313-framework-code">13.1.3 &nbsp; Framework code<a class="headerlink" href="#1313-framework-code" title="Permanent link">&para;</a></h2>
<p>Next, we attempt to distill the main framework of "trying, retreating, and pruning" from backtracking to enhance the code's universality.</p>
<p>Now, let's try to distill the main framework of "trial, retreat, and prune" from backtracking to enhance the code's universality.</p>
<p>In the following framework code, <code>state</code> represents the current state of the problem, <code>choices</code> represents the choices available under the current state:</p>
<div class="tabbed-set tabbed-alternate" data-tabs="5:14"><input checked="checked" id="__tabbed_5_1" name="__tabbed_5" type="radio" /><input id="__tabbed_5_2" name="__tabbed_5" type="radio" /><input id="__tabbed_5_3" name="__tabbed_5" type="radio" /><input id="__tabbed_5_4" name="__tabbed_5" type="radio" /><input id="__tabbed_5_5" name="__tabbed_5" type="radio" /><input id="__tabbed_5_6" name="__tabbed_5" type="radio" /><input id="__tabbed_5_7" name="__tabbed_5" type="radio" /><input id="__tabbed_5_8" name="__tabbed_5" type="radio" /><input id="__tabbed_5_9" name="__tabbed_5" type="radio" /><input id="__tabbed_5_10" name="__tabbed_5" type="radio" /><input id="__tabbed_5_11" name="__tabbed_5" type="radio" /><input id="__tabbed_5_12" name="__tabbed_5" type="radio" /><input id="__tabbed_5_13" name="__tabbed_5" type="radio" /><input id="__tabbed_5_14" name="__tabbed_5" type="radio" /><div class="tabbed-labels"><label for="__tabbed_5_1">Python</label><label for="__tabbed_5_2">C++</label><label for="__tabbed_5_3">Java</label><label for="__tabbed_5_4">C#</label><label for="__tabbed_5_5">Go</label><label for="__tabbed_5_6">Swift</label><label for="__tabbed_5_7">JS</label><label for="__tabbed_5_8">TS</label><label for="__tabbed_5_9">Dart</label><label for="__tabbed_5_10">Rust</label><label for="__tabbed_5_11">C</label><label for="__tabbed_5_12">Kotlin</label><label for="__tabbed_5_13">Ruby</label><label for="__tabbed_5_14">Zig</label></div>
<div class="tabbed-content">
@@ -4040,9 +4040,9 @@
<a id="__codelineno-42-8" name="__codelineno-42-8" href="#__codelineno-42-8"></a> <span class="k">return</span>
<a id="__codelineno-42-9" name="__codelineno-42-9" href="#__codelineno-42-9"></a> <span class="c1"># Iterate through all choices</span>
<a id="__codelineno-42-10" name="__codelineno-42-10" href="#__codelineno-42-10"></a> <span class="k">for</span> <span class="n">choice</span> <span class="ow">in</span> <span class="n">choices</span><span class="p">:</span>
<a id="__codelineno-42-11" name="__codelineno-42-11" href="#__codelineno-42-11"></a> <span class="c1"># Pruning: check if the choice is valid</span>
<a id="__codelineno-42-11" name="__codelineno-42-11" href="#__codelineno-42-11"></a> <span class="c1"># Prune: check if the choice is valid</span>
<a id="__codelineno-42-12" name="__codelineno-42-12" href="#__codelineno-42-12"></a> <span class="k">if</span> <span class="n">is_valid</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">choice</span><span class="p">):</span>
<a id="__codelineno-42-13" name="__codelineno-42-13" href="#__codelineno-42-13"></a> <span class="c1"># Try: make a choice, update the state</span>
<a id="__codelineno-42-13" name="__codelineno-42-13" href="#__codelineno-42-13"></a> <span class="c1"># Trial: make a choice, update the state</span>
<a id="__codelineno-42-14" name="__codelineno-42-14" href="#__codelineno-42-14"></a> <span class="n">make_choice</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">choice</span><span class="p">)</span>
<a id="__codelineno-42-15" name="__codelineno-42-15" href="#__codelineno-42-15"></a> <span class="n">backtrack</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">choices</span><span class="p">,</span> <span class="n">res</span><span class="p">)</span>
<a id="__codelineno-42-16" name="__codelineno-42-16" href="#__codelineno-42-16"></a> <span class="c1"># Retreat: undo the choice, revert to the previous state</span>
@@ -4061,9 +4061,9 @@
<a id="__codelineno-43-9" name="__codelineno-43-9" href="#__codelineno-43-9"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-43-10" name="__codelineno-43-10" href="#__codelineno-43-10"></a><span class="w"> </span><span class="c1">// Iterate through all choices</span>
<a id="__codelineno-43-11" name="__codelineno-43-11" href="#__codelineno-43-11"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">Choice</span><span class="w"> </span><span class="n">choice</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">choices</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-43-12" name="__codelineno-43-12" href="#__codelineno-43-12"></a><span class="w"> </span><span class="c1">// Pruning: check if the choice is valid</span>
<a id="__codelineno-43-12" name="__codelineno-43-12" href="#__codelineno-43-12"></a><span class="w"> </span><span class="c1">// Prune: check if the choice is valid</span>
<a id="__codelineno-43-13" name="__codelineno-43-13" href="#__codelineno-43-13"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">isValid</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">choice</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-43-14" name="__codelineno-43-14" href="#__codelineno-43-14"></a><span class="w"> </span><span class="c1">// Try: make a choice, update the state</span>
<a id="__codelineno-43-14" name="__codelineno-43-14" href="#__codelineno-43-14"></a><span class="w"> </span><span class="c1">// Trial: make a choice, update the state</span>
<a id="__codelineno-43-15" name="__codelineno-43-15" href="#__codelineno-43-15"></a><span class="w"> </span><span class="n">makeChoice</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">choice</span><span class="p">);</span>
<a id="__codelineno-43-16" name="__codelineno-43-16" href="#__codelineno-43-16"></a><span class="w"> </span><span class="n">backtrack</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">choices</span><span class="p">,</span><span class="w"> </span><span class="n">res</span><span class="p">);</span>
<a id="__codelineno-43-17" name="__codelineno-43-17" href="#__codelineno-43-17"></a><span class="w"> </span><span class="c1">// Retreat: undo the choice, revert to the previous state</span>
@@ -4085,9 +4085,9 @@
<a id="__codelineno-44-9" name="__codelineno-44-9" href="#__codelineno-44-9"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-44-10" name="__codelineno-44-10" href="#__codelineno-44-10"></a><span class="w"> </span><span class="c1">// Iterate through all choices</span>
<a id="__codelineno-44-11" name="__codelineno-44-11" href="#__codelineno-44-11"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">Choice</span><span class="w"> </span><span class="n">choice</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">choices</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-44-12" name="__codelineno-44-12" href="#__codelineno-44-12"></a><span class="w"> </span><span class="c1">// Pruning: check if the choice is valid</span>
<a id="__codelineno-44-12" name="__codelineno-44-12" href="#__codelineno-44-12"></a><span class="w"> </span><span class="c1">// Prune: check if the choice is valid</span>
<a id="__codelineno-44-13" name="__codelineno-44-13" href="#__codelineno-44-13"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">isValid</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">choice</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-44-14" name="__codelineno-44-14" href="#__codelineno-44-14"></a><span class="w"> </span><span class="c1">// Try: make a choice, update the state</span>
<a id="__codelineno-44-14" name="__codelineno-44-14" href="#__codelineno-44-14"></a><span class="w"> </span><span class="c1">// Trial: make a choice, update the state</span>
<a id="__codelineno-44-15" name="__codelineno-44-15" href="#__codelineno-44-15"></a><span class="w"> </span><span class="n">makeChoice</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">choice</span><span class="p">);</span>
<a id="__codelineno-44-16" name="__codelineno-44-16" href="#__codelineno-44-16"></a><span class="w"> </span><span class="n">backtrack</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">choices</span><span class="p">,</span><span class="w"> </span><span class="n">res</span><span class="p">);</span>
<a id="__codelineno-44-17" name="__codelineno-44-17" href="#__codelineno-44-17"></a><span class="w"> </span><span class="c1">// Retreat: undo the choice, revert to the previous state</span>
@@ -4109,9 +4109,9 @@
<a id="__codelineno-45-9" name="__codelineno-45-9" href="#__codelineno-45-9"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-45-10" name="__codelineno-45-10" href="#__codelineno-45-10"></a><span class="w"> </span><span class="c1">// Iterate through all choices</span>
<a id="__codelineno-45-11" name="__codelineno-45-11" href="#__codelineno-45-11"></a><span class="w"> </span><span class="k">foreach</span><span class="w"> </span><span class="p">(</span><span class="n">Choice</span><span class="w"> </span><span class="n">choice</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">choices</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-45-12" name="__codelineno-45-12" href="#__codelineno-45-12"></a><span class="w"> </span><span class="c1">// Pruning: check if the choice is valid</span>
<a id="__codelineno-45-12" name="__codelineno-45-12" href="#__codelineno-45-12"></a><span class="w"> </span><span class="c1">// Prune: check if the choice is valid</span>
<a id="__codelineno-45-13" name="__codelineno-45-13" href="#__codelineno-45-13"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">IsValid</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">choice</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-45-14" name="__codelineno-45-14" href="#__codelineno-45-14"></a><span class="w"> </span><span class="c1">// Try: make a choice, update the state</span>
<a id="__codelineno-45-14" name="__codelineno-45-14" href="#__codelineno-45-14"></a><span class="w"> </span><span class="c1">// Trial: make a choice, update the state</span>
<a id="__codelineno-45-15" name="__codelineno-45-15" href="#__codelineno-45-15"></a><span class="w"> </span><span class="n">MakeChoice</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">choice</span><span class="p">);</span>
<a id="__codelineno-45-16" name="__codelineno-45-16" href="#__codelineno-45-16"></a><span class="w"> </span><span class="n">Backtrack</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">choices</span><span class="p">,</span><span class="w"> </span><span class="n">res</span><span class="p">);</span>
<a id="__codelineno-45-17" name="__codelineno-45-17" href="#__codelineno-45-17"></a><span class="w"> </span><span class="c1">// Retreat: undo the choice, revert to the previous state</span>
@@ -4133,9 +4133,9 @@
<a id="__codelineno-46-9" name="__codelineno-46-9" href="#__codelineno-46-9"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-46-10" name="__codelineno-46-10" href="#__codelineno-46-10"></a><span class="w"> </span><span class="c1">// Iterate through all choices</span>
<a id="__codelineno-46-11" name="__codelineno-46-11" href="#__codelineno-46-11"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">choice</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">choices</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-46-12" name="__codelineno-46-12" href="#__codelineno-46-12"></a><span class="w"> </span><span class="c1">// Pruning: check if the choice is valid</span>
<a id="__codelineno-46-12" name="__codelineno-46-12" href="#__codelineno-46-12"></a><span class="w"> </span><span class="c1">// Prune: check if the choice is valid</span>
<a id="__codelineno-46-13" name="__codelineno-46-13" href="#__codelineno-46-13"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">isValid</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">choice</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-46-14" name="__codelineno-46-14" href="#__codelineno-46-14"></a><span class="w"> </span><span class="c1">// Try: make a choice, update the state</span>
<a id="__codelineno-46-14" name="__codelineno-46-14" href="#__codelineno-46-14"></a><span class="w"> </span><span class="c1">// Trial: make a choice, update the state</span>
<a id="__codelineno-46-15" name="__codelineno-46-15" href="#__codelineno-46-15"></a><span class="w"> </span><span class="nx">makeChoice</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">choice</span><span class="p">)</span>
<a id="__codelineno-46-16" name="__codelineno-46-16" href="#__codelineno-46-16"></a><span class="w"> </span><span class="nx">backtrack</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">choices</span><span class="p">,</span><span class="w"> </span><span class="nx">res</span><span class="p">)</span>
<a id="__codelineno-46-17" name="__codelineno-46-17" href="#__codelineno-46-17"></a><span class="w"> </span><span class="c1">// Retreat: undo the choice, revert to the previous state</span>
@@ -4157,9 +4157,9 @@
<a id="__codelineno-47-9" name="__codelineno-47-9" href="#__codelineno-47-9"></a> <span class="p">}</span>
<a id="__codelineno-47-10" name="__codelineno-47-10" href="#__codelineno-47-10"></a> <span class="c1">// Iterate through all choices</span>
<a id="__codelineno-47-11" name="__codelineno-47-11" href="#__codelineno-47-11"></a> <span class="k">for</span> <span class="n">choice</span> <span class="k">in</span> <span class="n">choices</span> <span class="p">{</span>
<a id="__codelineno-47-12" name="__codelineno-47-12" href="#__codelineno-47-12"></a> <span class="c1">// Pruning: check if the choice is valid</span>
<a id="__codelineno-47-12" name="__codelineno-47-12" href="#__codelineno-47-12"></a> <span class="c1">// Prune: check if the choice is valid</span>
<a id="__codelineno-47-13" name="__codelineno-47-13" href="#__codelineno-47-13"></a> <span class="k">if</span> <span class="n">isValid</span><span class="p">(</span><span class="n">state</span><span class="p">:</span> <span class="n">state</span><span class="p">,</span> <span class="n">choice</span><span class="p">:</span> <span class="n">choice</span><span class="p">)</span> <span class="p">{</span>
<a id="__codelineno-47-14" name="__codelineno-47-14" href="#__codelineno-47-14"></a> <span class="c1">// Try: make a choice, update the state</span>
<a id="__codelineno-47-14" name="__codelineno-47-14" href="#__codelineno-47-14"></a> <span class="c1">// Trial: make a choice, update the state</span>
<a id="__codelineno-47-15" name="__codelineno-47-15" href="#__codelineno-47-15"></a> <span class="n">makeChoice</span><span class="p">(</span><span class="n">state</span><span class="p">:</span> <span class="p">&amp;</span><span class="n">state</span><span class="p">,</span> <span class="n">choice</span><span class="p">:</span> <span class="n">choice</span><span class="p">)</span>
<a id="__codelineno-47-16" name="__codelineno-47-16" href="#__codelineno-47-16"></a> <span class="n">backtrack</span><span class="p">(</span><span class="n">state</span><span class="p">:</span> <span class="p">&amp;</span><span class="n">state</span><span class="p">,</span> <span class="n">choices</span><span class="p">:</span> <span class="n">choices</span><span class="p">,</span> <span class="n">res</span><span class="p">:</span> <span class="p">&amp;</span><span class="n">res</span><span class="p">)</span>
<a id="__codelineno-47-17" name="__codelineno-47-17" href="#__codelineno-47-17"></a> <span class="c1">// Retreat: undo the choice, revert to the previous state</span>
@@ -4181,9 +4181,9 @@
<a id="__codelineno-48-9" name="__codelineno-48-9" href="#__codelineno-48-9"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-48-10" name="__codelineno-48-10" href="#__codelineno-48-10"></a><span class="w"> </span><span class="c1">// Iterate through all choices</span>
<a id="__codelineno-48-11" name="__codelineno-48-11" href="#__codelineno-48-11"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">choice</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nx">choices</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-48-12" name="__codelineno-48-12" href="#__codelineno-48-12"></a><span class="w"> </span><span class="c1">// Pruning: check if the choice is valid</span>
<a id="__codelineno-48-12" name="__codelineno-48-12" href="#__codelineno-48-12"></a><span class="w"> </span><span class="c1">// Prune: check if the choice is valid</span>
<a id="__codelineno-48-13" name="__codelineno-48-13" href="#__codelineno-48-13"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">isValid</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">choice</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-48-14" name="__codelineno-48-14" href="#__codelineno-48-14"></a><span class="w"> </span><span class="c1">// Try: make a choice, update the state</span>
<a id="__codelineno-48-14" name="__codelineno-48-14" href="#__codelineno-48-14"></a><span class="w"> </span><span class="c1">// Trial: make a choice, update the state</span>
<a id="__codelineno-48-15" name="__codelineno-48-15" href="#__codelineno-48-15"></a><span class="w"> </span><span class="nx">makeChoice</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">choice</span><span class="p">);</span>
<a id="__codelineno-48-16" name="__codelineno-48-16" href="#__codelineno-48-16"></a><span class="w"> </span><span class="nx">backtrack</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">choices</span><span class="p">,</span><span class="w"> </span><span class="nx">res</span><span class="p">);</span>
<a id="__codelineno-48-17" name="__codelineno-48-17" href="#__codelineno-48-17"></a><span class="w"> </span><span class="c1">// Retreat: undo the choice, revert to the previous state</span>
@@ -4205,9 +4205,9 @@
<a id="__codelineno-49-9" name="__codelineno-49-9" href="#__codelineno-49-9"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-49-10" name="__codelineno-49-10" href="#__codelineno-49-10"></a><span class="w"> </span><span class="c1">// Iterate through all choices</span>
<a id="__codelineno-49-11" name="__codelineno-49-11" href="#__codelineno-49-11"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">choice</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nx">choices</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-49-12" name="__codelineno-49-12" href="#__codelineno-49-12"></a><span class="w"> </span><span class="c1">// Pruning: check if the choice is valid</span>
<a id="__codelineno-49-12" name="__codelineno-49-12" href="#__codelineno-49-12"></a><span class="w"> </span><span class="c1">// Prune: check if the choice is valid</span>
<a id="__codelineno-49-13" name="__codelineno-49-13" href="#__codelineno-49-13"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">isValid</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">choice</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-49-14" name="__codelineno-49-14" href="#__codelineno-49-14"></a><span class="w"> </span><span class="c1">// Try: make a choice, update the state</span>
<a id="__codelineno-49-14" name="__codelineno-49-14" href="#__codelineno-49-14"></a><span class="w"> </span><span class="c1">// Trial: make a choice, update the state</span>
<a id="__codelineno-49-15" name="__codelineno-49-15" href="#__codelineno-49-15"></a><span class="w"> </span><span class="nx">makeChoice</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">choice</span><span class="p">);</span>
<a id="__codelineno-49-16" name="__codelineno-49-16" href="#__codelineno-49-16"></a><span class="w"> </span><span class="nx">backtrack</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">choices</span><span class="p">,</span><span class="w"> </span><span class="nx">res</span><span class="p">);</span>
<a id="__codelineno-49-17" name="__codelineno-49-17" href="#__codelineno-49-17"></a><span class="w"> </span><span class="c1">// Retreat: undo the choice, revert to the previous state</span>
@@ -4229,9 +4229,9 @@
<a id="__codelineno-50-9" name="__codelineno-50-9" href="#__codelineno-50-9"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-50-10" name="__codelineno-50-10" href="#__codelineno-50-10"></a><span class="w"> </span><span class="c1">// Iterate through all choices</span>
<a id="__codelineno-50-11" name="__codelineno-50-11" href="#__codelineno-50-11"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">Choice</span><span class="w"> </span><span class="n">choice</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">choices</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-50-12" name="__codelineno-50-12" href="#__codelineno-50-12"></a><span class="w"> </span><span class="c1">// Pruning: check if the choice is valid</span>
<a id="__codelineno-50-12" name="__codelineno-50-12" href="#__codelineno-50-12"></a><span class="w"> </span><span class="c1">// Prune: check if the choice is valid</span>
<a id="__codelineno-50-13" name="__codelineno-50-13" href="#__codelineno-50-13"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">isValid</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">choice</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-50-14" name="__codelineno-50-14" href="#__codelineno-50-14"></a><span class="w"> </span><span class="c1">// Try: make a choice, update the state</span>
<a id="__codelineno-50-14" name="__codelineno-50-14" href="#__codelineno-50-14"></a><span class="w"> </span><span class="c1">// Trial: make a choice, update the state</span>
<a id="__codelineno-50-15" name="__codelineno-50-15" href="#__codelineno-50-15"></a><span class="w"> </span><span class="n">makeChoice</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">choice</span><span class="p">);</span>
<a id="__codelineno-50-16" name="__codelineno-50-16" href="#__codelineno-50-16"></a><span class="w"> </span><span class="n">backtrack</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">choices</span><span class="p">,</span><span class="w"> </span><span class="n">res</span><span class="p">);</span>
<a id="__codelineno-50-17" name="__codelineno-50-17" href="#__codelineno-50-17"></a><span class="w"> </span><span class="c1">// Retreat: undo the choice, revert to the previous state</span>
@@ -4253,9 +4253,9 @@
<a id="__codelineno-51-9" name="__codelineno-51-9" href="#__codelineno-51-9"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-51-10" name="__codelineno-51-10" href="#__codelineno-51-10"></a><span class="w"> </span><span class="c1">// Iterate through all choices</span>
<a id="__codelineno-51-11" name="__codelineno-51-11" href="#__codelineno-51-11"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">choice</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">choices</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-51-12" name="__codelineno-51-12" href="#__codelineno-51-12"></a><span class="w"> </span><span class="c1">// Pruning: check if the choice is valid</span>
<a id="__codelineno-51-12" name="__codelineno-51-12" href="#__codelineno-51-12"></a><span class="w"> </span><span class="c1">// Prune: check if the choice is valid</span>
<a id="__codelineno-51-13" name="__codelineno-51-13" href="#__codelineno-51-13"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">is_valid</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">choice</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-51-14" name="__codelineno-51-14" href="#__codelineno-51-14"></a><span class="w"> </span><span class="c1">// Try: make a choice, update the state</span>
<a id="__codelineno-51-14" name="__codelineno-51-14" href="#__codelineno-51-14"></a><span class="w"> </span><span class="c1">// Trial: make a choice, update the state</span>
<a id="__codelineno-51-15" name="__codelineno-51-15" href="#__codelineno-51-15"></a><span class="w"> </span><span class="n">make_choice</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">choice</span><span class="p">);</span>
<a id="__codelineno-51-16" name="__codelineno-51-16" href="#__codelineno-51-16"></a><span class="w"> </span><span class="n">backtrack</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">choices</span><span class="p">,</span><span class="w"> </span><span class="n">res</span><span class="p">);</span>
<a id="__codelineno-51-17" name="__codelineno-51-17" href="#__codelineno-51-17"></a><span class="w"> </span><span class="c1">// Retreat: undo the choice, revert to the previous state</span>
@@ -4277,9 +4277,9 @@
<a id="__codelineno-52-9" name="__codelineno-52-9" href="#__codelineno-52-9"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-52-10" name="__codelineno-52-10" href="#__codelineno-52-10"></a><span class="w"> </span><span class="c1">// Iterate through all choices</span>
<a id="__codelineno-52-11" name="__codelineno-52-11" href="#__codelineno-52-11"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">numChoices</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-52-12" name="__codelineno-52-12" href="#__codelineno-52-12"></a><span class="w"> </span><span class="c1">// Pruning: check if the choice is valid</span>
<a id="__codelineno-52-12" name="__codelineno-52-12" href="#__codelineno-52-12"></a><span class="w"> </span><span class="c1">// Prune: check if the choice is valid</span>
<a id="__codelineno-52-13" name="__codelineno-52-13" href="#__codelineno-52-13"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">isValid</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">choices</span><span class="p">[</span><span class="n">i</span><span class="p">]))</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-52-14" name="__codelineno-52-14" href="#__codelineno-52-14"></a><span class="w"> </span><span class="c1">// Try: make a choice, update the state</span>
<a id="__codelineno-52-14" name="__codelineno-52-14" href="#__codelineno-52-14"></a><span class="w"> </span><span class="c1">// Trial: make a choice, update the state</span>
<a id="__codelineno-52-15" name="__codelineno-52-15" href="#__codelineno-52-15"></a><span class="w"> </span><span class="n">makeChoice</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">choices</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
<a id="__codelineno-52-16" name="__codelineno-52-16" href="#__codelineno-52-16"></a><span class="w"> </span><span class="n">backtrack</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">choices</span><span class="p">,</span><span class="w"> </span><span class="n">numChoices</span><span class="p">,</span><span class="w"> </span><span class="n">res</span><span class="p">,</span><span class="w"> </span><span class="n">numRes</span><span class="p">);</span>
<a id="__codelineno-52-17" name="__codelineno-52-17" href="#__codelineno-52-17"></a><span class="w"> </span><span class="c1">// Retreat: undo the choice, revert to the previous state</span>
@@ -4301,9 +4301,9 @@
<a id="__codelineno-53-9" name="__codelineno-53-9" href="#__codelineno-53-9"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-53-10" name="__codelineno-53-10" href="#__codelineno-53-10"></a><span class="w"> </span><span class="c1">// Iterate through all choices</span>
<a id="__codelineno-53-11" name="__codelineno-53-11" href="#__codelineno-53-11"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">choice</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">choices</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-53-12" name="__codelineno-53-12" href="#__codelineno-53-12"></a><span class="w"> </span><span class="c1">// Pruning: check if the choice is valid</span>
<a id="__codelineno-53-12" name="__codelineno-53-12" href="#__codelineno-53-12"></a><span class="w"> </span><span class="c1">// Prune: check if the choice is valid</span>
<a id="__codelineno-53-13" name="__codelineno-53-13" href="#__codelineno-53-13"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">isValid</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">choice</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-53-14" name="__codelineno-53-14" href="#__codelineno-53-14"></a><span class="w"> </span><span class="c1">// Try: make a choice, update the state</span>
<a id="__codelineno-53-14" name="__codelineno-53-14" href="#__codelineno-53-14"></a><span class="w"> </span><span class="c1">// Trial: make a choice, update the state</span>
<a id="__codelineno-53-15" name="__codelineno-53-15" href="#__codelineno-53-15"></a><span class="w"> </span><span class="n">makeChoice</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">choice</span><span class="p">)</span>
<a id="__codelineno-53-16" name="__codelineno-53-16" href="#__codelineno-53-16"></a><span class="w"> </span><span class="n">backtrack</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">choices</span><span class="p">,</span><span class="w"> </span><span class="n">res</span><span class="p">)</span>
<a id="__codelineno-53-17" name="__codelineno-53-17" href="#__codelineno-53-17"></a><span class="w"> </span><span class="c1">// Retreat: undo the choice, revert to the previous state</span>
@@ -4323,7 +4323,7 @@
</div>
</div>
</div>
<p>Next, we solve Example Three based on the framework code. The <code>state</code> is the node traversal path, <code>choices</code> are the current node's left and right children, and the result <code>res</code> is the list of paths:</p>
<p>Now, we are able to solve Example Three using the framework code. The <code>state</code> is the node traversal path, <code>choices</code> are the current node's left and right children, and the result <code>res</code> is the list of paths:</p>
<div class="tabbed-set tabbed-alternate" data-tabs="6:14"><input checked="checked" id="__tabbed_6_1" name="__tabbed_6" type="radio" /><input id="__tabbed_6_2" name="__tabbed_6" type="radio" /><input id="__tabbed_6_3" name="__tabbed_6" type="radio" /><input id="__tabbed_6_4" name="__tabbed_6" type="radio" /><input id="__tabbed_6_5" name="__tabbed_6" type="radio" /><input id="__tabbed_6_6" name="__tabbed_6" type="radio" /><input id="__tabbed_6_7" name="__tabbed_6" type="radio" /><input id="__tabbed_6_8" name="__tabbed_6" type="radio" /><input id="__tabbed_6_9" name="__tabbed_6" type="radio" /><input id="__tabbed_6_10" name="__tabbed_6" type="radio" /><input id="__tabbed_6_11" name="__tabbed_6" type="radio" /><input id="__tabbed_6_12" name="__tabbed_6" type="radio" /><input id="__tabbed_6_13" name="__tabbed_6" type="radio" /><input id="__tabbed_6_14" name="__tabbed_6" type="radio" /><div class="tabbed-labels"><label for="__tabbed_6_1">Python</label><label for="__tabbed_6_2">C++</label><label for="__tabbed_6_3">Java</label><label for="__tabbed_6_4">C#</label><label for="__tabbed_6_5">Go</label><label for="__tabbed_6_6">Swift</label><label for="__tabbed_6_7">JS</label><label for="__tabbed_6_8">TS</label><label for="__tabbed_6_9">Dart</label><label for="__tabbed_6_10">Rust</label><label for="__tabbed_6_11">C</label><label for="__tabbed_6_12">Kotlin</label><label for="__tabbed_6_13">Ruby</label><label for="__tabbed_6_14">Zig</label></div>
<div class="tabbed-content">
<div class="tabbed-block">
@@ -4620,11 +4620,11 @@
</div>
</div>
</div>
<p>As per the requirements, after finding a node with a value of <span class="arithmatex">\(7\)</span>, the search should continue, <strong>thus the <code>return</code> statement after recording the solution should be removed</strong>. Figure 13-4 compares the search processes with and without retaining the <code>return</code> statement.</p>
<p>As per the requirements, after finding a node with a value of <span class="arithmatex">\(7\)</span>, the search should continue. <strong>As a result, the <code>return</code> statement after recording the solution should be removed</strong>. Figure 13-4 compares the search processes with and without retaining the <code>return</code> statement.</p>
<p><a class="glightbox" href="../backtracking_algorithm.assets/backtrack_remove_return_or_not.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="Comparison of retaining and removing the return in the search process" class="animation-figure" src="../backtracking_algorithm.assets/backtrack_remove_return_or_not.png" /></a></p>
<p align="center"> Figure 13-4 &nbsp; Comparison of retaining and removing the return in the search process </p>
<p>Compared to the implementation based on pre-order traversal, the code implementation based on the backtracking algorithm framework seems verbose, but it has better universality. In fact, <strong>many backtracking problems can be solved within this framework</strong>. We just need to define <code>state</code> and <code>choices</code> according to the specific problem and implement the methods in the framework.</p>
<p>Compared to the implementation based on pre-order traversal, the code using the backtracking algorithm framework seems verbose. However, it has better universality. In fact, <strong>many backtracking problems can be solved within this framework</strong>. We just need to define <code>state</code> and <code>choices</code> according to the specific problem and implement the methods in the framework.</p>
<h2 id="1314-common-terminology">13.1.4 &nbsp; Common terminology<a class="headerlink" href="#1314-common-terminology" title="Permanent link">&para;</a></h2>
<p>To analyze algorithmic problems more clearly, we summarize the meanings of commonly used terminology in backtracking algorithms and provide corresponding examples from Example Three as shown in Table 13-1.</p>
<p align="center"> Table 13-1 &nbsp; Common backtracking algorithm terminology </p>
@@ -4640,34 +4640,34 @@
</thead>
<tbody>
<tr>
<td>Solution (solution)</td>
<td>Solution</td>
<td>A solution is an answer that satisfies specific conditions of the problem, which may have one or more</td>
<td>All paths from the root node to node <span class="arithmatex">\(7\)</span> that meet the constraint</td>
</tr>
<tr>
<td>Constraint (constraint)</td>
<td>Constraint</td>
<td>Constraints are conditions in the problem that limit the feasibility of solutions, often used for pruning</td>
<td>Paths do not contain node <span class="arithmatex">\(3\)</span></td>
</tr>
<tr>
<td>State (state)</td>
<td>State</td>
<td>State represents the situation of the problem at a certain moment, including choices made</td>
<td>Current visited node path, i.e., <code>path</code> node list</td>
</tr>
<tr>
<td>Attempt (attempt)</td>
<td>An attempt is the process of exploring the solution space based on available choices, including making choices, updating the state, and checking if it's a solution</td>
<td>Trial</td>
<td>A trial is the process of exploring the solution space based on available choices, including making choices, updating the state, and checking if it's a solution</td>
<td>Recursively visiting left (right) child nodes, adding nodes to <code>path</code>, checking if the node's value is <span class="arithmatex">\(7\)</span></td>
</tr>
<tr>
<td>Backtracking (backtracking)</td>
<td>Backtracking refers to the action of undoing previous choices and returning to the previous state when encountering states that do not meet the constraints</td>
<td>When passing leaf nodes, ending node visits, encountering nodes with a value of <span class="arithmatex">\(3\)</span>, terminating the search, and function return</td>
<td>Retreat</td>
<td>Retreat refers to the action of undoing previous choices and returning to the previous state when encountering states that do not meet the constraints</td>
<td>When passing leaf nodes, ending node visits, encountering nodes with a value of <span class="arithmatex">\(3\)</span>, terminating the search, and the recursion function returns</td>
</tr>
<tr>
<td>Pruning (pruning)</td>
<td>Pruning is a method to avoid meaningless search paths based on the characteristics and constraints of the problem, which can enhance search efficiency</td>
<td>When encountering a node with a value of <span class="arithmatex">\(3\)</span>, no further search is continued</td>
<td>Prune</td>
<td>Prune is a method to avoid meaningless search paths based on the characteristics and constraints of the problem, which can enhance search efficiency</td>
<td>When encountering a node with a value of <span class="arithmatex">\(3\)</span>, no further search is required</td>
</tr>
</tbody>
</table>
@@ -4678,14 +4678,14 @@
</div>
<h2 id="1315-advantages-and-limitations">13.1.5 &nbsp; Advantages and limitations<a class="headerlink" href="#1315-advantages-and-limitations" title="Permanent link">&para;</a></h2>
<p>The backtracking algorithm is essentially a depth-first search algorithm that attempts all possible solutions until a satisfying solution is found. The advantage of this method is that it can find all possible solutions, and with reasonable pruning operations, it can be highly efficient.</p>
<p>However, when dealing with large-scale or complex problems, <strong>the operational efficiency of backtracking may be difficult to accept</strong>.</p>
<p>However, when dealing with large-scale or complex problems, <strong>the running efficiency of backtracking algorithm may not be acceptable</strong>.</p>
<ul>
<li><strong>Time</strong>: Backtracking algorithms usually need to traverse all possible states in the state space, which can reach exponential or factorial time complexity.</li>
<li><strong>Space</strong>: In recursive calls, it is necessary to save the current state (such as paths, auxiliary variables for pruning, etc.). When the depth is very large, the space requirement may become significant.</li>
<li><strong>Time complexity</strong>: Backtracking algorithms usually need to traverse all possible states in the state space, which can reach exponential or factorial time complexity.</li>
<li><strong>Space complexity</strong>: In recursive calls, it is necessary to save the current state (such as paths, auxiliary variables for pruning, etc.). When the depth is very large, the space need may become significantly bigger.</li>
</ul>
<p>Even so, <strong>backtracking remains the best solution for certain search problems and constraint satisfaction problems</strong>. For these problems, since it is unpredictable which choices can generate valid solutions, we must traverse all possible choices. In this case, <strong>the key is how to optimize efficiency</strong>, with common efficiency optimization methods being two types.</p>
<p>Even so, <strong>backtracking remains the best solution for certain search problems and constraint satisfaction problems</strong>. For these problems, there is no way to predict which choices can generate valid solutions. We have to traverse all possible choices. In this case, <strong>the key is about how to optimize the efficiency</strong>. There are two common efficiency optimization methods.</p>
<ul>
<li><strong>Pruning</strong>: Avoid searching paths that definitely will not produce a solution, thus saving time and space.</li>
<li><strong>Prune</strong>: Avoid searching paths that definitely will not produce a solution, thus saving time and space.</li>
<li><strong>Heuristic search</strong>: Introduce some strategies or estimates during the search process to prioritize the paths that are most likely to produce valid solutions.</li>
</ul>
<h2 id="1316-typical-backtracking-problems">13.1.6 &nbsp; Typical backtracking problems<a class="headerlink" href="#1316-typical-backtracking-problems" title="Permanent link">&para;</a></h2>
@@ -3604,38 +3604,38 @@
<h1 id="134-n-queens-problem">13.4 &nbsp; n queens problem<a class="headerlink" href="#134-n-queens-problem" title="Permanent link">&para;</a></h1>
<div class="admonition question">
<p class="admonition-title">Question</p>
<p>According to the rules of chess, a queen can attack pieces in the same row, column, or on a diagonal line. Given <span class="arithmatex">\(n\)</span> queens and an <span class="arithmatex">\(n \times n\)</span> chessboard, find arrangements where no two queens can attack each other.</p>
<p>According to the rules of chess, a queen can attack pieces in the same row, column, or diagonal line. Given <span class="arithmatex">\(n\)</span> queens and an <span class="arithmatex">\(n \times n\)</span> chessboard, find arrangements where no two queens can attack each other.</p>
</div>
<p>As shown in Figure 13-15, when <span class="arithmatex">\(n = 4\)</span>, there are two solutions. From the perspective of the backtracking algorithm, an <span class="arithmatex">\(n \times n\)</span> chessboard has <span class="arithmatex">\(n^2\)</span> squares, presenting all possible choices <code>choices</code>. The state of the chessboard <code>state</code> changes continuously as each queen is placed.</p>
<p>As shown in Figure 13-15, there are two solutions when <span class="arithmatex">\(n = 4\)</span>. From the perspective of the backtracking algorithm, an <span class="arithmatex">\(n \times n\)</span> chessboard has <span class="arithmatex">\(n^2\)</span> squares, presenting all possible choices <code>choices</code>. The state of the chessboard <code>state</code> changes continuously as each queen is placed.</p>
<p><a class="glightbox" href="../n_queens_problem.assets/solution_4_queens.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="Solution to the 4 queens problem" class="animation-figure" src="../n_queens_problem.assets/solution_4_queens.png" /></a></p>
<p align="center"> Figure 13-15 &nbsp; Solution to the 4 queens problem </p>
<p>Figure 13-16 shows the three constraints of this problem: <strong>multiple queens cannot be on the same row, column, or diagonal</strong>. It is important to note that diagonals are divided into the main diagonal <code>\</code> and the secondary diagonal <code>/</code>.</p>
<p>Figure 13-16 shows the three constraints of this problem: <strong>multiple queens cannot occupy the same row, column, or diagonal</strong>. It is important to note that diagonals are divided into the main diagonal <code>\</code> and the secondary diagonal <code>/</code>.</p>
<p><a class="glightbox" href="../n_queens_problem.assets/n_queens_constraints.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="Constraints of the n queens problem" class="animation-figure" src="../n_queens_problem.assets/n_queens_constraints.png" /></a></p>
<p align="center"> Figure 13-16 &nbsp; Constraints of the n queens problem </p>
<h3 id="1-row-by-row-placing-strategy">1. &nbsp; Row-by-row placing strategy<a class="headerlink" href="#1-row-by-row-placing-strategy" title="Permanent link">&para;</a></h3>
<p>As the number of queens equals the number of rows on the chessboard, both being <span class="arithmatex">\(n\)</span>, it is easy to conclude: <strong>each row on the chessboard allows and only allows one queen to be placed</strong>.</p>
<p>As the number of queens equals the number of rows on the chessboard, both being <span class="arithmatex">\(n\)</span>, it is easy to conclude that <strong>each row on the chessboard allows and only allows one queen to be placed</strong>.</p>
<p>This means that we can adopt a row-by-row placing strategy: starting from the first row, place one queen per row until the last row is reached.</p>
<p>Figure 13-17 shows the row-by-row placing process for the 4 queens problem. Due to space limitations, the figure only expands one search branch of the first row, and prunes any placements that do not meet the column and diagonal constraints.</p>
<p><a class="glightbox" href="../n_queens_problem.assets/n_queens_placing.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="Row-by-row placing strategy" class="animation-figure" src="../n_queens_problem.assets/n_queens_placing.png" /></a></p>
<p align="center"> Figure 13-17 &nbsp; Row-by-row placing strategy </p>
<p>Essentially, <strong>the row-by-row placing strategy serves as a pruning function</strong>, avoiding all search branches that would place multiple queens in the same row.</p>
<p>Essentially, <strong>the row-by-row placing strategy serves as a pruning function</strong>, eliminating all search branches that would place multiple queens in the same row.</p>
<h3 id="2-column-and-diagonal-pruning">2. &nbsp; Column and diagonal pruning<a class="headerlink" href="#2-column-and-diagonal-pruning" title="Permanent link">&para;</a></h3>
<p>To satisfy column constraints, we can use a boolean array <code>cols</code> of length <span class="arithmatex">\(n\)</span> to track whether a queen occupies each column. Before each placement decision, <code>cols</code> is used to prune the columns that already have queens, and it is dynamically updated during backtracking.</p>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>Note that the origin of the chessboard is located in the upper left corner, where the row index increases from top to bottom, and the column index increases from left to right.</p>
<p>Note that the origin of the matrix is located in the upper left corner, where the row index increases from top to bottom, and the column index increases from left to right.</p>
</div>
<p>How about the diagonal constraints? Let the row and column indices of a cell on the chessboard be <span class="arithmatex">\((row, col)\)</span>. By selecting a specific main diagonal, we notice that the difference <span class="arithmatex">\(row - col\)</span> is the same for all cells on that diagonal, <strong>meaning that <span class="arithmatex">\(row - col\)</span> is a constant value on that diagonal</strong>.</p>
<p>Thus, if two cells satisfy <span class="arithmatex">\(row_1 - col_1 = row_2 - col_2\)</span>, they are definitely on the same main diagonal. Using this pattern, we can utilize the array <code>diags1</code> shown in Figure 13-18 to track whether a queen is on any main diagonal.</p>
<p>Similarly, <strong>the sum <span class="arithmatex">\(row + col\)</span> is a constant value for all cells on a secondary diagonal</strong>. We can also use the array <code>diags2</code> to handle secondary diagonal constraints.</p>
<p>How about the diagonal constraints? Let the row and column indices of a certain cell on the chessboard be <span class="arithmatex">\((row, col)\)</span>. By selecting a specific main diagonal, we notice that the difference <span class="arithmatex">\(row - col\)</span> is the same for all cells on that diagonal, <strong>meaning that <span class="arithmatex">\(row - col\)</span> is a constant value on the main diagonal</strong>.</p>
<p>In other words, if two cells satisfy <span class="arithmatex">\(row_1 - col_1 = row_2 - col_2\)</span>, they are definitely on the same main diagonal. Using this pattern, we can utilize the array <code>diags1</code> shown in Figure 13-18 to track whether a queen is on any main diagonal.</p>
<p>Similarly, <strong>the sum of <span class="arithmatex">\(row + col\)</span> is a constant value for all cells on the secondary diagonal</strong>. We can also use the array <code>diags2</code> to handle secondary diagonal constraints.</p>
<p><a class="glightbox" href="../n_queens_problem.assets/n_queens_cols_diagonals.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="Handling column and diagonal constraints" class="animation-figure" src="../n_queens_problem.assets/n_queens_cols_diagonals.png" /></a></p>
<p align="center"> Figure 13-18 &nbsp; Handling column and diagonal constraints </p>
<h3 id="3-code-implementation">3. &nbsp; Code implementation<a class="headerlink" href="#3-code-implementation" title="Permanent link">&para;</a></h3>
<p>Please note, in an <span class="arithmatex">\(n\)</span>-dimensional matrix, the range of <span class="arithmatex">\(row - col\)</span> is <span class="arithmatex">\([-n + 1, n - 1]\)</span>, and the range of <span class="arithmatex">\(row + col\)</span> is <span class="arithmatex">\([0, 2n - 2]\)</span>, thus the number of both main and secondary diagonals is <span class="arithmatex">\(2n - 1\)</span>, meaning the length of both arrays <code>diags1</code> and <code>diags2</code> is <span class="arithmatex">\(2n - 1\)</span>.</p>
<p>Please note, in an <span class="arithmatex">\(n\)</span>-dimensional square matrix, the range of <span class="arithmatex">\(row - col\)</span> is <span class="arithmatex">\([-n + 1, n - 1]\)</span>, and the range of <span class="arithmatex">\(row + col\)</span> is <span class="arithmatex">\([0, 2n - 2]\)</span>. Consequently, the number of both main and secondary diagonals is <span class="arithmatex">\(2n - 1\)</span>, meaning the length of the arrays <code>diags1</code> and <code>diags2</code> is <span class="arithmatex">\(2n - 1\)</span>.</p>
<div class="tabbed-set tabbed-alternate" data-tabs="1:14"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><input id="__tabbed_1_3" name="__tabbed_1" type="radio" /><input id="__tabbed_1_4" name="__tabbed_1" type="radio" /><input id="__tabbed_1_5" name="__tabbed_1" type="radio" /><input id="__tabbed_1_6" name="__tabbed_1" type="radio" /><input id="__tabbed_1_7" name="__tabbed_1" type="radio" /><input id="__tabbed_1_8" name="__tabbed_1" type="radio" /><input id="__tabbed_1_9" name="__tabbed_1" type="radio" /><input id="__tabbed_1_10" name="__tabbed_1" type="radio" /><input id="__tabbed_1_11" name="__tabbed_1" type="radio" /><input id="__tabbed_1_12" name="__tabbed_1" type="radio" /><input id="__tabbed_1_13" name="__tabbed_1" type="radio" /><input id="__tabbed_1_14" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">Python</label><label for="__tabbed_1_2">C++</label><label for="__tabbed_1_3">Java</label><label for="__tabbed_1_4">C#</label><label for="__tabbed_1_5">Go</label><label for="__tabbed_1_6">Swift</label><label for="__tabbed_1_7">JS</label><label for="__tabbed_1_8">TS</label><label for="__tabbed_1_9">Dart</label><label for="__tabbed_1_10">Rust</label><label for="__tabbed_1_11">C</label><label for="__tabbed_1_12">Kotlin</label><label for="__tabbed_1_13">Ruby</label><label for="__tabbed_1_14">Zig</label></div>
<div class="tabbed-content">
<div class="tabbed-block">
@@ -3847,8 +3847,8 @@
</div>
</div>
</div>
<p>Placing <span class="arithmatex">\(n\)</span> queens row-by-row, considering column constraints, from the first row to the last row there are <span class="arithmatex">\(n\)</span>, <span class="arithmatex">\(n-1\)</span>, <span class="arithmatex">\(\dots\)</span>, <span class="arithmatex">\(2\)</span>, <span class="arithmatex">\(1\)</span> choices, using <span class="arithmatex">\(O(n!)\)</span> time. When recording a solution, it is necessary to copy the matrix <code>state</code> and add it to <code>res</code>, with the copying operation using <span class="arithmatex">\(O(n^2)\)</span> time. Therefore, <strong>the overall time complexity is <span class="arithmatex">\(O(n! \cdot n^2)\)</span></strong>. In practice, pruning based on diagonal constraints can significantly reduce the search space, thus often the search efficiency is better than the above time complexity.</p>
<p>Array <code>state</code> uses <span class="arithmatex">\(O(n^2)\)</span> space, and arrays <code>cols</code>, <code>diags1</code>, and <code>diags2</code> each use <span class="arithmatex">\(O(n)\)</span> space. The maximum recursion depth is <span class="arithmatex">\(n\)</span>, using <span class="arithmatex">\(O(n)\)</span> stack space. Therefore, <strong>the space complexity is <span class="arithmatex">\(O(n^2)\)</span></strong>.</p>
<p>Placing <span class="arithmatex">\(n\)</span> queens row-by-row, considering column constraints, from the first row to the last row, there are <span class="arithmatex">\(n\)</span>, <span class="arithmatex">\(n-1\)</span>, <span class="arithmatex">\(\dots\)</span>, <span class="arithmatex">\(2\)</span>, <span class="arithmatex">\(1\)</span> choices, using <span class="arithmatex">\(O(n!)\)</span> time. When recording a solution, it is necessary to copy the matrix <code>state</code> and add it to <code>res</code>, with the copying operation using <span class="arithmatex">\(O(n^2)\)</span> time. Therefore, <strong>the overall time complexity is <span class="arithmatex">\(O(n! \cdot n^2)\)</span></strong>. In practice, pruning based on diagonal constraints can significantly reduce the search space, thus often the search efficiency is better than the aforementioned time complexity.</p>
<p>Array <code>state</code> uses <span class="arithmatex">\(O(n^2)\)</span> space, and arrays <code>cols</code>, <code>diags1</code>, and <code>diags2</code> each use <span class="arithmatex">\(O(n)\)</span> space as well. The maximum recursion depth is <span class="arithmatex">\(n\)</span>, using <span class="arithmatex">\(O(n)\)</span> stack frame space. Therefore, <strong>the space complexity is <span class="arithmatex">\(O(n^2)\)</span></strong>.</p>
<!-- Source file information -->
+11 -11
View File
@@ -3586,23 +3586,23 @@
<h1 id="135-summary">13.5 &nbsp; Summary<a class="headerlink" href="#135-summary" title="Permanent link">&para;</a></h1>
<h3 id="1-key-review">1. &nbsp; Key review<a class="headerlink" href="#1-key-review" title="Permanent link">&para;</a></h3>
<ul>
<li>The essence of the backtracking algorithm is an exhaustive search method, where the solution space is traversed deeply first to find solutions that meet the criteria. During the search, if a satisfying solution is found, it is recorded, until all solutions are found or the search is completed.</li>
<li>The search process of the backtracking algorithm includes trying and retreating. It uses depth-first search to explore various choices, and when a choice does not meet the constraint conditions, the previous choice is undone, reverting to the previous state, and other options are then continued to be tried. Trying and retreating are operations in opposite directions.</li>
<li>Backtracking problems usually contain multiple constraints, which can be used to perform pruning operations. Pruning can terminate unnecessary search branches early, greatly enhancing search efficiency.</li>
<li>Backtracking algorithms are mainly used to solve search problems and constraint satisfaction problems. Although combinatorial optimization problems can be solved using backtracking, there are often more efficient or effective solutions available.</li>
<li>The permutation problem aims to search for all possible permutations of a given set of elements. We use an array to record whether each element has been chosen, cutting off branches that repeatedly select the same element, ensuring each element is selected only once.</li>
<li>The essence of the backtracking algorithm is exhaustive search. It seeks solutions that meet the conditions by performing a depth-first traversal of the solution space. During the search, if a satisfying solution is found, it is recorded, until all solutions are found or the traversal is completed.</li>
<li>The search process of the backtracking algorithm includes trying and backtracking. It uses depth-first search to explore various choices, and when a choice does not meet the constraints, the previous choice is undone. Then it reverts to the previous state and continues to try other options. Trying and backtracking are operations in opposite directions.</li>
<li>Backtracking problems usually contain multiple constraints. These constraints can be used to perform pruning operations. Pruning can terminate unnecessary search branches in advance, greatly enhancing search efficiency.</li>
<li>The backtracking algorithm is mainly used to solve search problems and constraint satisfaction problems. Although combinatorial optimization problems can be solved using backtracking, there are often more efficient or effective solutions available.</li>
<li>The permutation problem aims to search for all possible permutations of the elements in a given set. We use an array to record whether each element has been chosen, avoiding repeated selection of the same element. This ensures that each element is chosen only once.</li>
<li>In permutation problems, if the set contains duplicate elements, the final result will include duplicate permutations. We need to restrict that identical elements can only be selected once in each round, which is usually implemented using a hash set.</li>
<li>The subset-sum problem aims to find all subsets in a given set that sum to a target value. The set does not distinguish the order of elements, but the search process outputs all ordered results, producing duplicate subsets. Before backtracking, we sort the data and set a variable to indicate the starting point of each round of traversal, thereby pruning the search branches that generate duplicate subsets.</li>
<li>For the subset-sum problem, equal elements in the array can produce duplicate sets. Using the precondition that the array is already sorted, we prune by determining if adjacent elements are equal, thus ensuring equal elements are only selected once per round.</li>
<li>The <span class="arithmatex">\(n\)</span> queens problem aims to find schemes to place <span class="arithmatex">\(n\)</span> queens on an <span class="arithmatex">\(n \times n\)</span> size chessboard in such a way that no two queens can attack each other. The constraints of the problem include row constraints, column constraints, main diagonal constraints, and secondary diagonal constraints. To meet the row constraint, we adopt a strategy of placing one queen per row, ensuring each row has one queen placed.</li>
<li>The handling of column constraints and diagonal constraints is similar. For column constraints, we use an array to record whether there is a queen in each column, thereby indicating whether the selected cell is legal. For diagonal constraints, we use two arrays to respectively record the presence of queens on the main and secondary diagonals; the challenge is in identifying the row and column index patterns that satisfy the same primary (secondary) diagonal.</li>
<li>The subset-sum problem aims to find all subsets in a given set that sum to a target value. The set does not distinguish the order of elements, but the search process may generate duplicate subsets. This occurs because the algorithm explores different element orders as unique paths. Before backtracking, we sort the data and set a variable to indicate the starting point of the traversal for each round. This allows us to prune the search branches that generate duplicate subsets.</li>
<li>For the subset-sum problem, equal elements in the array can produce duplicate sets. Using the precondition that the array is already sorted, we prune by determining if adjacent elements are equal. This ensures that equal elements are only selected once per round.</li>
<li>The <span class="arithmatex">\(n\)</span> queens problem aims to find schemes to place <span class="arithmatex">\(n\)</span> queens on an <span class="arithmatex">\(n \times n\)</span> chessboard such that no two queens can attack each other. The constraints of the problem include row constraints, column constraints, and constraints on the main and secondary diagonals. To meet the row constraint, we adopt a strategy of placing one queen per row, ensuring each row has one queen placed.</li>
<li>The handling of column constraints and diagonal constraints is similar. For column constraints, we use an array to record whether there is a queen in each column, thereby indicating whether the selected cell is legal. For diagonal constraints, we use two arrays to respectively record the presence of queens on the main and secondary diagonals. The challenge is to determine the relationship between row and column indices for cells on the same main or secondary diagonal.</li>
</ul>
<h3 id="2-q-a">2. &nbsp; Q &amp; A<a class="headerlink" href="#2-q-a" title="Permanent link">&para;</a></h3>
<p><strong>Q</strong>: How can we understand the relationship between backtracking and recursion?</p>
<p>Overall, backtracking is a "strategic algorithm," while recursion is more of a "tool."</p>
<p>Overall, backtracking is an "algorithmic strategy," while recursion is more of a "tool."</p>
<ul>
<li>Backtracking algorithms are typically based on recursion. However, backtracking is one of the application scenarios of recursion, specifically in search problems.</li>
<li>The structure of recursion reflects the "sub-problem decomposition" problem-solving paradigm, commonly used in solving problems involving divide and conquer, backtracking, and dynamic programming (memoized recursion).</li>
<li>The structure of recursion reflects the problem-solving paradigm of "sub-problem decomposition." It is commonly used in solving problems involving divide and conquer, backtracking, and dynamic programming (memoized recursion).</li>
</ul>
<!-- Source file information -->
+1 -1
View File
@@ -4296,7 +4296,7 @@
<p align="center"> Figure 7-4 &nbsp; Perfect binary tree </p>
<h3 id="2-complete-binary-tree">2. &nbsp; Complete binary tree<a class="headerlink" href="#2-complete-binary-tree" title="Permanent link">&para;</a></h3>
<p>As shown in Figure 7-5, a <u>complete binary tree</u> is a binary tree where only the nodes in the bottom level are not completely filled, and the nodes in the bottom level are filled from left to right as much as possible. Please note that a perfect binary tree is also a complete binary tree.</p>
<p>As shown in Figure 7-5, a <u>complete binary tree</u> is a binary tree where only the bottom level is possibly not completely filled, and nodes at the bottom level must be filled continuously from left to right. Note that a perfect binary tree is also a complete binary tree.</p>
<p><a class="glightbox" href="../binary_tree.assets/complete_binary_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="Complete binary tree" class="animation-figure" src="../binary_tree.assets/complete_binary_tree.png" /></a></p>
<p align="center"> Figure 7-5 &nbsp; Complete binary tree </p>
+1 -1
View File
@@ -8,4 +8,4 @@ document$.subscribe(({ body }) => {
],
});
});
/*! update cache: 20250427154041 */
/*! update cache: 20250427165403 */
+1 -1
View File
@@ -15,4 +15,4 @@ window.MathJax = {
document$.subscribe(() => {
MathJax.typesetPromise();
});
/*! update cache: 20250427154041 */
/*! update cache: 20250427165403 */
File diff suppressed because one or more lines are too long
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -552,4 +552,4 @@ a:hover .text-button span {
width: 100%;
height: 100%;
}
/*! update cache: 20250427154041 */
/*! update cache: 20250427165403 */
+1 -1
View File
@@ -8,4 +8,4 @@ document$.subscribe(({ body }) => {
],
});
});
/*! update cache: 20250427154024 */
/*! update cache: 20250427165346 */
+1 -1
View File
@@ -15,4 +15,4 @@ window.MathJax = {
document$.subscribe(() => {
MathJax.typesetPromise();
});
/*! update cache: 20250427154024 */
/*! update cache: 20250427165346 */
File diff suppressed because one or more lines are too long
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -552,4 +552,4 @@ a:hover .text-button span {
width: 100%;
height: 100%;
}
/*! update cache: 20250427154024 */
/*! update cache: 20250427165346 */
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -4336,7 +4336,7 @@
<p align="center"> 圖 7-4 &nbsp; 完美二元樹 </p>
<h3 id="2_1">2. &nbsp; 完全二元樹<a class="headerlink" href="#2_1" title="Permanent link">&para;</a></h3>
<p>如圖 7-5 所示,<u>完全二元樹(complete binary tree</u>只有最底層的節點未被填滿,且最底層節點儘量靠左填充。請注意,完美二元樹也是一棵完全二元樹。</p>
<p>如圖 7-5 所示,<u>完全二元樹(complete binary tree</u>僅允許最底層的節點不完全填滿,且最底層節點必須從左至右依次連續填充。請注意,完美二元樹也是一棵完全二元樹。</p>
<p><a class="glightbox" href="../binary_tree.assets/complete_binary_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="完全二元樹" class="animation-figure" src="../binary_tree.assets/complete_binary_tree.png" /></a></p>
<p align="center"> 圖 7-5 &nbsp; 完全二元樹 </p>
+1 -1
View File
@@ -8,4 +8,4 @@ document$.subscribe(({ body }) => {
],
});
});
/*! update cache: 20250427154036 */
/*! update cache: 20250427165358 */
+1 -1
View File
@@ -15,4 +15,4 @@ window.MathJax = {
document$.subscribe(() => {
MathJax.typesetPromise();
});
/*! update cache: 20250427154036 */
/*! update cache: 20250427165358 */
File diff suppressed because one or more lines are too long
Binary file not shown.
+1 -1
View File
@@ -552,4 +552,4 @@ a:hover .text-button span {
width: 100%;
height: 100%;
}
/*! update cache: 20250427154036 */
/*! update cache: 20250427165358 */