mirror of
https://github.com/krahets/hello-algo.git
synced 2026-07-09 22:16:06 +00:00
deploy
This commit is contained in:
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
@@ -2638,7 +2638,7 @@
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#1315" class="md-nav__link">
|
||||
13.1.5 优势与局限性
|
||||
13.1.5 优点与局限性
|
||||
</a>
|
||||
|
||||
</li>
|
||||
@@ -3370,7 +3370,7 @@
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#1315" class="md-nav__link">
|
||||
13.1.5 优势与局限性
|
||||
13.1.5 优点与局限性
|
||||
</a>
|
||||
|
||||
</li>
|
||||
@@ -3439,12 +3439,12 @@
|
||||
<!-- Page content -->
|
||||
<h1 id="131">13.1 回溯算法<a class="headerlink" href="#131" title="Permanent link">¶</a></h1>
|
||||
<p>「回溯算法 backtracking algorithm」是一种通过穷举来解决问题的方法,它的核心思想是从一个初始状态出发,暴力搜索所有可能的解决方案,当遇到正确的解则将其记录,直到找到解或者尝试了所有可能的选择都无法找到解为止。</p>
|
||||
<p>回溯算法通常采用“深度优先搜索”来遍历解空间。在二叉树章节中,我们提到前序、中序和后序遍历都属于深度优先搜索。接下来,我们利用前序遍历构造一个回溯问题,逐步了解回溯算法的工作原理。</p>
|
||||
<p>回溯算法通常采用“深度优先搜索”来遍历解空间。在“二叉树”章节中,我们提到前序、中序和后序遍历都属于深度优先搜索。接下来,我们利用前序遍历构造一个回溯问题,逐步了解回溯算法的工作原理。</p>
|
||||
<div class="admonition question">
|
||||
<p class="admonition-title">例题一</p>
|
||||
<p>给定一个二叉树,搜索并记录所有值为 <span class="arithmatex">\(7\)</span> 的节点,请返回节点列表。</p>
|
||||
<p>给定一棵二叉树,搜索并记录所有值为 <span class="arithmatex">\(7\)</span> 的节点,请返回节点列表。</p>
|
||||
</div>
|
||||
<p>对于此题,我们前序遍历这颗树,并判断当前节点的值是否为 <span class="arithmatex">\(7\)</span> ,若是则将该节点的值加入到结果列表 <code>res</code> 之中。相关过程实现如图 13-1 和以下代码所示。</p>
|
||||
<p>对于此题,我们前序遍历这棵树,并判断当前节点的值是否为 <span class="arithmatex">\(7\)</span> ,若是,则将该节点的值加入结果列表 <code>res</code> 之中。相关过程实现如图 13-1 和以下代码所示:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="1:12"><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" /><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">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
@@ -3628,7 +3628,7 @@
|
||||
<p class="admonition-title">例题二</p>
|
||||
<p>在二叉树中搜索所有值为 <span class="arithmatex">\(7\)</span> 的节点,<strong>请返回根节点到这些节点的路径</strong>。</p>
|
||||
</div>
|
||||
<p>在例题一代码的基础上,我们需要借助一个列表 <code>path</code> 记录访问过的节点路径。当访问到值为 <span class="arithmatex">\(7\)</span> 的节点时,则复制 <code>path</code> 并添加进结果列表 <code>res</code> 。遍历完成后,<code>res</code> 中保存的就是所有的解。</p>
|
||||
<p>在例题一代码的基础上,我们需要借助一个列表 <code>path</code> 记录访问过的节点路径。当访问到值为 <span class="arithmatex">\(7\)</span> 的节点时,则复制 <code>path</code> 并添加进结果列表 <code>res</code> 。遍历完成后,<code>res</code> 中保存的就是所有的解。代码如下所示:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="2:12"><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" /><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">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
@@ -3858,7 +3858,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<p>在每次“尝试”中,我们通过将当前节点添加进 <code>path</code> 来记录路径;而在“回退”前,我们需要将该节点从 <code>path</code> 中弹出,<strong>以恢复本次尝试之前的状态</strong>。</p>
|
||||
<p>观察图 13-2 所示的过程,<strong>我们可以将尝试和回退理解为“前进”与“撤销”</strong>,两个操作是互为逆向的。</p>
|
||||
<p>观察图 13-2 所示的过程,<strong>我们可以将尝试和回退理解为“前进”与“撤销”</strong>,两个操作互为逆向。</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"><1></label><label for="__tabbed_3_2"><2></label><label for="__tabbed_3_3"><3></label><label for="__tabbed_3_4"><4></label><label for="__tabbed_3_5"><5></label><label for="__tabbed_3_6"><6></label><label for="__tabbed_3_7"><7></label><label for="__tabbed_3_8"><8></label><label for="__tabbed_3_9"><9></label><label for="__tabbed_3_10"><10></label><label for="__tabbed_3_11"><11></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
@@ -3904,7 +3904,7 @@
|
||||
<p class="admonition-title">例题三</p>
|
||||
<p>在二叉树中搜索所有值为 <span class="arithmatex">\(7\)</span> 的节点,请返回根节点到这些节点的路径,<strong>并要求路径中不包含值为 <span class="arithmatex">\(3\)</span> 的节点</strong>。</p>
|
||||
</div>
|
||||
<p>为了满足以上约束条件,<strong>我们需要添加剪枝操作</strong>:在搜索过程中,若遇到值为 <span class="arithmatex">\(3\)</span> 的节点,则提前返回,停止继续搜索。</p>
|
||||
<p>为了满足以上约束条件,<strong>我们需要添加剪枝操作</strong>:在搜索过程中,若遇到值为 <span class="arithmatex">\(3\)</span> 的节点,则提前返回,不再继续搜索。代码如下所示:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="4:12"><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" /><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">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
@@ -4143,13 +4143,13 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>剪枝是一个非常形象的名词。如图 13-3 所示,在搜索过程中,<strong>我们“剪掉”了不满足约束条件的搜索分支</strong>,避免许多无意义的尝试,从而提高了搜索效率。</p>
|
||||
<p>“剪枝”是一个非常形象的名词。如图 13-3 所示,在搜索过程中,<strong>我们“剪掉”了不满足约束条件的搜索分支</strong>,避免许多无意义的尝试,从而提高了搜索效率。</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="根据约束条件剪枝" class="animation-figure" src="../backtracking_algorithm.assets/preorder_find_constrained_paths.png" /></a></p>
|
||||
<p align="center"> 图 13-3 根据约束条件剪枝 </p>
|
||||
|
||||
<h2 id="1313">13.1.3 框架代码<a class="headerlink" href="#1313" title="Permanent link">¶</a></h2>
|
||||
<p>接下来,我们尝试将回溯的“尝试、回退、剪枝”的主体框架提炼出来,提升代码的通用性。</p>
|
||||
<p>在以下框架代码中,<code>state</code> 表示问题的当前状态,<code>choices</code> 表示当前状态下可以做出的选择。</p>
|
||||
<p>在以下框架代码中,<code>state</code> 表示问题的当前状态,<code>choices</code> 表示当前状态下可以做出的选择:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="5:12"><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" /><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">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
@@ -4159,7 +4159,7 @@
|
||||
<a id="__codelineno-36-4" name="__codelineno-36-4" href="#__codelineno-36-4"></a> <span class="k">if</span> <span class="n">is_solution</span><span class="p">(</span><span class="n">state</span><span class="p">):</span>
|
||||
<a id="__codelineno-36-5" name="__codelineno-36-5" href="#__codelineno-36-5"></a> <span class="c1"># 记录解</span>
|
||||
<a id="__codelineno-36-6" name="__codelineno-36-6" href="#__codelineno-36-6"></a> <span class="n">record_solution</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">res</span><span class="p">)</span>
|
||||
<a id="__codelineno-36-7" name="__codelineno-36-7" href="#__codelineno-36-7"></a> <span class="c1"># 停止继续搜索</span>
|
||||
<a id="__codelineno-36-7" name="__codelineno-36-7" href="#__codelineno-36-7"></a> <span class="c1"># 不再继续搜索</span>
|
||||
<a id="__codelineno-36-8" name="__codelineno-36-8" href="#__codelineno-36-8"></a> <span class="k">return</span>
|
||||
<a id="__codelineno-36-9" name="__codelineno-36-9" href="#__codelineno-36-9"></a> <span class="c1"># 遍历所有选择</span>
|
||||
<a id="__codelineno-36-10" name="__codelineno-36-10" href="#__codelineno-36-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>
|
||||
@@ -4179,7 +4179,7 @@
|
||||
<a id="__codelineno-37-4" name="__codelineno-37-4" href="#__codelineno-37-4"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">isSolution</span><span class="p">(</span><span class="n">state</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-37-5" name="__codelineno-37-5" href="#__codelineno-37-5"></a><span class="w"> </span><span class="c1">// 记录解</span>
|
||||
<a id="__codelineno-37-6" name="__codelineno-37-6" href="#__codelineno-37-6"></a><span class="w"> </span><span class="n">recordSolution</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">res</span><span class="p">);</span>
|
||||
<a id="__codelineno-37-7" name="__codelineno-37-7" href="#__codelineno-37-7"></a><span class="w"> </span><span class="c1">// 停止继续搜索</span>
|
||||
<a id="__codelineno-37-7" name="__codelineno-37-7" href="#__codelineno-37-7"></a><span class="w"> </span><span class="c1">// 不再继续搜索</span>
|
||||
<a id="__codelineno-37-8" name="__codelineno-37-8" href="#__codelineno-37-8"></a><span class="w"> </span><span class="k">return</span><span class="p">;</span>
|
||||
<a id="__codelineno-37-9" name="__codelineno-37-9" href="#__codelineno-37-9"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-37-10" name="__codelineno-37-10" href="#__codelineno-37-10"></a><span class="w"> </span><span class="c1">// 遍历所有选择</span>
|
||||
@@ -4203,7 +4203,7 @@
|
||||
<a id="__codelineno-38-4" name="__codelineno-38-4" href="#__codelineno-38-4"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">isSolution</span><span class="p">(</span><span class="n">state</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-38-5" name="__codelineno-38-5" href="#__codelineno-38-5"></a><span class="w"> </span><span class="c1">// 记录解</span>
|
||||
<a id="__codelineno-38-6" name="__codelineno-38-6" href="#__codelineno-38-6"></a><span class="w"> </span><span class="n">recordSolution</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">res</span><span class="p">);</span>
|
||||
<a id="__codelineno-38-7" name="__codelineno-38-7" href="#__codelineno-38-7"></a><span class="w"> </span><span class="c1">// 停止继续搜索</span>
|
||||
<a id="__codelineno-38-7" name="__codelineno-38-7" href="#__codelineno-38-7"></a><span class="w"> </span><span class="c1">// 不再继续搜索</span>
|
||||
<a id="__codelineno-38-8" name="__codelineno-38-8" href="#__codelineno-38-8"></a><span class="w"> </span><span class="k">return</span><span class="p">;</span>
|
||||
<a id="__codelineno-38-9" name="__codelineno-38-9" href="#__codelineno-38-9"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-38-10" name="__codelineno-38-10" href="#__codelineno-38-10"></a><span class="w"> </span><span class="c1">// 遍历所有选择</span>
|
||||
@@ -4227,7 +4227,7 @@
|
||||
<a id="__codelineno-39-4" name="__codelineno-39-4" href="#__codelineno-39-4"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">IsSolution</span><span class="p">(</span><span class="n">state</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-39-5" name="__codelineno-39-5" href="#__codelineno-39-5"></a><span class="w"> </span><span class="c1">// 记录解</span>
|
||||
<a id="__codelineno-39-6" name="__codelineno-39-6" href="#__codelineno-39-6"></a><span class="w"> </span><span class="n">RecordSolution</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">res</span><span class="p">);</span>
|
||||
<a id="__codelineno-39-7" name="__codelineno-39-7" href="#__codelineno-39-7"></a><span class="w"> </span><span class="c1">// 停止继续搜索</span>
|
||||
<a id="__codelineno-39-7" name="__codelineno-39-7" href="#__codelineno-39-7"></a><span class="w"> </span><span class="c1">// 不再继续搜索</span>
|
||||
<a id="__codelineno-39-8" name="__codelineno-39-8" href="#__codelineno-39-8"></a><span class="w"> </span><span class="k">return</span><span class="p">;</span>
|
||||
<a id="__codelineno-39-9" name="__codelineno-39-9" href="#__codelineno-39-9"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-39-10" name="__codelineno-39-10" href="#__codelineno-39-10"></a><span class="w"> </span><span class="c1">// 遍历所有选择</span>
|
||||
@@ -4251,7 +4251,7 @@
|
||||
<a id="__codelineno-40-4" name="__codelineno-40-4" href="#__codelineno-40-4"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">isSolution</span><span class="p">(</span><span class="nx">state</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-40-5" name="__codelineno-40-5" href="#__codelineno-40-5"></a><span class="w"> </span><span class="c1">// 记录解</span>
|
||||
<a id="__codelineno-40-6" name="__codelineno-40-6" href="#__codelineno-40-6"></a><span class="w"> </span><span class="nx">recordSolution</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">res</span><span class="p">)</span>
|
||||
<a id="__codelineno-40-7" name="__codelineno-40-7" href="#__codelineno-40-7"></a><span class="w"> </span><span class="c1">// 停止继续搜索</span>
|
||||
<a id="__codelineno-40-7" name="__codelineno-40-7" href="#__codelineno-40-7"></a><span class="w"> </span><span class="c1">// 不再继续搜索</span>
|
||||
<a id="__codelineno-40-8" name="__codelineno-40-8" href="#__codelineno-40-8"></a><span class="w"> </span><span class="k">return</span>
|
||||
<a id="__codelineno-40-9" name="__codelineno-40-9" href="#__codelineno-40-9"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-40-10" name="__codelineno-40-10" href="#__codelineno-40-10"></a><span class="w"> </span><span class="c1">// 遍历所有选择</span>
|
||||
@@ -4275,7 +4275,7 @@
|
||||
<a id="__codelineno-41-4" name="__codelineno-41-4" href="#__codelineno-41-4"></a> <span class="k">if</span> <span class="n">isSolution</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="p">{</span>
|
||||
<a id="__codelineno-41-5" name="__codelineno-41-5" href="#__codelineno-41-5"></a> <span class="c1">// 记录解</span>
|
||||
<a id="__codelineno-41-6" name="__codelineno-41-6" href="#__codelineno-41-6"></a> <span class="n">recordSolution</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">res</span><span class="p">:</span> <span class="p">&</span><span class="n">res</span><span class="p">)</span>
|
||||
<a id="__codelineno-41-7" name="__codelineno-41-7" href="#__codelineno-41-7"></a> <span class="c1">// 停止继续搜索</span>
|
||||
<a id="__codelineno-41-7" name="__codelineno-41-7" href="#__codelineno-41-7"></a> <span class="c1">// 不再继续搜索</span>
|
||||
<a id="__codelineno-41-8" name="__codelineno-41-8" href="#__codelineno-41-8"></a> <span class="k">return</span>
|
||||
<a id="__codelineno-41-9" name="__codelineno-41-9" href="#__codelineno-41-9"></a> <span class="p">}</span>
|
||||
<a id="__codelineno-41-10" name="__codelineno-41-10" href="#__codelineno-41-10"></a> <span class="c1">// 遍历所有选择</span>
|
||||
@@ -4299,7 +4299,7 @@
|
||||
<a id="__codelineno-42-4" name="__codelineno-42-4" href="#__codelineno-42-4"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">isSolution</span><span class="p">(</span><span class="nx">state</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-42-5" name="__codelineno-42-5" href="#__codelineno-42-5"></a><span class="w"> </span><span class="c1">// 记录解</span>
|
||||
<a id="__codelineno-42-6" name="__codelineno-42-6" href="#__codelineno-42-6"></a><span class="w"> </span><span class="nx">recordSolution</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">res</span><span class="p">);</span>
|
||||
<a id="__codelineno-42-7" name="__codelineno-42-7" href="#__codelineno-42-7"></a><span class="w"> </span><span class="c1">// 停止继续搜索</span>
|
||||
<a id="__codelineno-42-7" name="__codelineno-42-7" href="#__codelineno-42-7"></a><span class="w"> </span><span class="c1">// 不再继续搜索</span>
|
||||
<a id="__codelineno-42-8" name="__codelineno-42-8" href="#__codelineno-42-8"></a><span class="w"> </span><span class="k">return</span><span class="p">;</span>
|
||||
<a id="__codelineno-42-9" name="__codelineno-42-9" href="#__codelineno-42-9"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-42-10" name="__codelineno-42-10" href="#__codelineno-42-10"></a><span class="w"> </span><span class="c1">// 遍历所有选择</span>
|
||||
@@ -4323,7 +4323,7 @@
|
||||
<a id="__codelineno-43-4" name="__codelineno-43-4" href="#__codelineno-43-4"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">isSolution</span><span class="p">(</span><span class="nx">state</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-43-5" name="__codelineno-43-5" href="#__codelineno-43-5"></a><span class="w"> </span><span class="c1">// 记录解</span>
|
||||
<a id="__codelineno-43-6" name="__codelineno-43-6" href="#__codelineno-43-6"></a><span class="w"> </span><span class="nx">recordSolution</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">res</span><span class="p">);</span>
|
||||
<a id="__codelineno-43-7" name="__codelineno-43-7" href="#__codelineno-43-7"></a><span class="w"> </span><span class="c1">// 停止继续搜索</span>
|
||||
<a id="__codelineno-43-7" name="__codelineno-43-7" href="#__codelineno-43-7"></a><span class="w"> </span><span class="c1">// 不再继续搜索</span>
|
||||
<a id="__codelineno-43-8" name="__codelineno-43-8" href="#__codelineno-43-8"></a><span class="w"> </span><span class="k">return</span><span class="p">;</span>
|
||||
<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">// 遍历所有选择</span>
|
||||
@@ -4347,7 +4347,7 @@
|
||||
<a id="__codelineno-44-4" name="__codelineno-44-4" href="#__codelineno-44-4"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">isSolution</span><span class="p">(</span><span class="n">state</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-44-5" name="__codelineno-44-5" href="#__codelineno-44-5"></a><span class="w"> </span><span class="c1">// 记录解</span>
|
||||
<a id="__codelineno-44-6" name="__codelineno-44-6" href="#__codelineno-44-6"></a><span class="w"> </span><span class="n">recordSolution</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">res</span><span class="p">);</span>
|
||||
<a id="__codelineno-44-7" name="__codelineno-44-7" href="#__codelineno-44-7"></a><span class="w"> </span><span class="c1">// 停止继续搜索</span>
|
||||
<a id="__codelineno-44-7" name="__codelineno-44-7" href="#__codelineno-44-7"></a><span class="w"> </span><span class="c1">// 不再继续搜索</span>
|
||||
<a id="__codelineno-44-8" name="__codelineno-44-8" href="#__codelineno-44-8"></a><span class="w"> </span><span class="k">return</span><span class="p">;</span>
|
||||
<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">// 遍历所有选择</span>
|
||||
@@ -4371,7 +4371,7 @@
|
||||
<a id="__codelineno-45-4" name="__codelineno-45-4" href="#__codelineno-45-4"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">is_solution</span><span class="p">(</span><span class="n">state</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-45-5" name="__codelineno-45-5" href="#__codelineno-45-5"></a><span class="w"> </span><span class="c1">// 记录解</span>
|
||||
<a id="__codelineno-45-6" name="__codelineno-45-6" href="#__codelineno-45-6"></a><span class="w"> </span><span class="n">record_solution</span><span class="p">(</span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="n">res</span><span class="p">);</span>
|
||||
<a id="__codelineno-45-7" name="__codelineno-45-7" href="#__codelineno-45-7"></a><span class="w"> </span><span class="c1">// 停止继续搜索</span>
|
||||
<a id="__codelineno-45-7" name="__codelineno-45-7" href="#__codelineno-45-7"></a><span class="w"> </span><span class="c1">// 不再继续搜索</span>
|
||||
<a id="__codelineno-45-8" name="__codelineno-45-8" href="#__codelineno-45-8"></a><span class="w"> </span><span class="k">return</span><span class="p">;</span>
|
||||
<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">// 遍历所有选择</span>
|
||||
@@ -4395,7 +4395,7 @@
|
||||
<a id="__codelineno-46-4" name="__codelineno-46-4" href="#__codelineno-46-4"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">isSolution</span><span class="p">(</span><span class="n">state</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-46-5" name="__codelineno-46-5" href="#__codelineno-46-5"></a><span class="w"> </span><span class="c1">// 记录解</span>
|
||||
<a id="__codelineno-46-6" name="__codelineno-46-6" href="#__codelineno-46-6"></a><span class="w"> </span><span class="n">recordSolution</span><span class="p">(</span><span class="n">state</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-46-7" name="__codelineno-46-7" href="#__codelineno-46-7"></a><span class="w"> </span><span class="c1">// 停止继续搜索</span>
|
||||
<a id="__codelineno-46-7" name="__codelineno-46-7" href="#__codelineno-46-7"></a><span class="w"> </span><span class="c1">// 不再继续搜索</span>
|
||||
<a id="__codelineno-46-8" name="__codelineno-46-8" href="#__codelineno-46-8"></a><span class="w"> </span><span class="k">return</span><span class="p">;</span>
|
||||
<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">// 遍历所有选择</span>
|
||||
@@ -4418,7 +4418,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>接下来,我们基于框架代码来解决例题三。状态 <code>state</code> 为节点遍历路径,选择 <code>choices</code> 为当前节点的左子节点和右子节点,结果 <code>res</code> 是路径列表。</p>
|
||||
<p>接下来,我们基于框架代码来解决例题三。状态 <code>state</code> 为节点遍历路径,选择 <code>choices</code> 为当前节点的左子节点和右子节点,结果 <code>res</code> 是路径列表:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="6:12"><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" /><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">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
@@ -4977,9 +4977,9 @@
|
||||
<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="保留与删除 return 的搜索过程对比" class="animation-figure" src="../backtracking_algorithm.assets/backtrack_remove_return_or_not.png" /></a></p>
|
||||
<p align="center"> 图 13-4 保留与删除 return 的搜索过程对比 </p>
|
||||
|
||||
<p>相比基于前序遍历的代码实现,基于回溯算法框架的代码实现虽然显得啰嗦,但通用性更好。实际上,<strong>许多回溯问题都可以在该框架下解决</strong>。我们只需根据具体问题来定义 <code>state</code> 和 <code>choices</code> ,并实现框架中的各个方法即可。</p>
|
||||
<p>相比基于前序遍历的代码实现,基于回溯算法框架的代码实现虽然显得啰唆,但通用性更好。实际上,<strong>许多回溯问题可以在该框架下解决</strong>。我们只需根据具体问题来定义 <code>state</code> 和 <code>choices</code> ,并实现框架中的各个方法即可。</p>
|
||||
<h2 id="1314">13.1.4 常用术语<a class="headerlink" href="#1314" title="Permanent link">¶</a></h2>
|
||||
<p>为了更清晰地分析算法问题,我们总结一下回溯算法中常用术语的含义,并对照例题三给出对应示例。</p>
|
||||
<p>为了更清晰地分析算法问题,我们总结一下回溯算法中常用术语的含义,并对照例题三给出对应示例,如表 13-1 所示。</p>
|
||||
<p align="center"> 表 13-1 常见的回溯算法术语 </p>
|
||||
|
||||
<div class="center-table">
|
||||
@@ -4993,34 +4993,34 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>解 Solution</td>
|
||||
<td>解(solution)</td>
|
||||
<td>解是满足问题特定条件的答案,可能有一个或多个</td>
|
||||
<td>根节点到节点 <span class="arithmatex">\(7\)</span> 的满足约束条件的所有路径</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>约束条件 Constraint</td>
|
||||
<td>约束条件(constraint)</td>
|
||||
<td>约束条件是问题中限制解的可行性的条件,通常用于剪枝</td>
|
||||
<td>路径中不包含节点 <span class="arithmatex">\(3\)</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>状态 State</td>
|
||||
<td>状态(state)</td>
|
||||
<td>状态表示问题在某一时刻的情况,包括已经做出的选择</td>
|
||||
<td>当前已访问的节点路径,即 <code>path</code> 节点列表</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>尝试 Attempt</td>
|
||||
<td>尝试(attempt)</td>
|
||||
<td>尝试是根据可用选择来探索解空间的过程,包括做出选择,更新状态,检查是否为解</td>
|
||||
<td>递归访问左(右)子节点,将节点添加进 <code>path</code> ,判断节点的值是否为 <span class="arithmatex">\(7\)</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>回退 Backtracking</td>
|
||||
<td>回退(backtracking)</td>
|
||||
<td>回退指遇到不满足约束条件的状态时,撤销前面做出的选择,回到上一个状态</td>
|
||||
<td>当越过叶节点、结束节点访问、遇到值为 <span class="arithmatex">\(3\)</span> 的节点时终止搜索,函数返回</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>剪枝 Pruning</td>
|
||||
<td>剪枝(pruning)</td>
|
||||
<td>剪枝是根据问题特性和约束条件避免无意义的搜索路径的方法,可提高搜索效率</td>
|
||||
<td>当遇到值为 <span class="arithmatex">\(3\)</span> 的节点时,则终止继续搜索</td>
|
||||
<td>当遇到值为 <span class="arithmatex">\(3\)</span> 的节点时,则不再继续搜索</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -5029,14 +5029,14 @@
|
||||
<p class="admonition-title">Tip</p>
|
||||
<p>问题、解、状态等概念是通用的,在分治、回溯、动态规划、贪心等算法中都有涉及。</p>
|
||||
</div>
|
||||
<h2 id="1315">13.1.5 优势与局限性<a class="headerlink" href="#1315" title="Permanent link">¶</a></h2>
|
||||
<p>回溯算法本质上是一种深度优先搜索算法,它尝试所有可能的解决方案直到找到满足条件的解。这种方法的优势在于它能够找到所有可能的解决方案,而且在合理的剪枝操作下,具有很高的效率。</p>
|
||||
<h2 id="1315">13.1.5 优点与局限性<a class="headerlink" href="#1315" title="Permanent link">¶</a></h2>
|
||||
<p>回溯算法本质上是一种深度优先搜索算法,它尝试所有可能的解决方案直到找到满足条件的解。这种方法的优点在于能够找到所有可能的解决方案,而且在合理的剪枝操作下,具有很高的效率。</p>
|
||||
<p>然而,在处理大规模或者复杂问题时,<strong>回溯算法的运行效率可能难以接受</strong>。</p>
|
||||
<ul>
|
||||
<li><strong>时间</strong>:回溯算法通常需要遍历状态空间的所有可能,时间复杂度可以达到指数阶或阶乘阶。</li>
|
||||
<li><strong>空间</strong>:在递归调用中需要保存当前的状态(例如路径、用于剪枝的辅助变量等),当深度很大时,空间需求可能会变得很大。</li>
|
||||
</ul>
|
||||
<p>即便如此,<strong>回溯算法仍然是某些搜索问题和约束满足问题的最佳解决方案</strong>。对于这些问题,由于无法预测哪些选择可生成有效的解,因此我们必须对所有可能的选择进行遍历。在这种情况下,<strong>关键是如何进行效率优化</strong>,常见的效率优化方法有两种。</p>
|
||||
<p>即便如此,<strong>回溯算法仍然是某些搜索问题和约束满足问题的最佳解决方案</strong>。对于这些问题,由于无法预测哪些选择可生成有效的解,因此我们必须对所有可能的选择进行遍历。在这种情况下,<strong>关键是如何优化效率</strong>,常见的效率优化方法有两种。</p>
|
||||
<ul>
|
||||
<li><strong>剪枝</strong>:避免搜索那些肯定不会产生解的路径,从而节省时间和空间。</li>
|
||||
<li><strong>启发式搜索</strong>:在搜索过程中引入一些策略或者估计值,从而优先搜索最有可能产生有效解的路径。</li>
|
||||
@@ -5047,7 +5047,7 @@
|
||||
<ul>
|
||||
<li>全排列问题:给定一个集合,求出其所有可能的排列组合。</li>
|
||||
<li>子集和问题:给定一个集合和一个目标和,找到集合中所有和为目标和的子集。</li>
|
||||
<li>汉诺塔问题:给定三个柱子和一系列大小不同的圆盘,要求将所有圆盘从一个柱子移动到另一个柱子,每次只能移动一个圆盘,且不能将大圆盘放在小圆盘上。</li>
|
||||
<li>汉诺塔问题:给定三根柱子和一系列大小不同的圆盘,要求将所有圆盘从一根柱子移动到另一根柱子,每次只能移动一个圆盘,且不能将大圆盘放在小圆盘上。</li>
|
||||
</ul>
|
||||
<p><strong>约束满足问题</strong>:这类问题的目标是找到满足所有约束条件的解。</p>
|
||||
<ul>
|
||||
@@ -5061,11 +5061,11 @@
|
||||
<li>旅行商问题:在一个图中,从一个点出发,访问所有其他点恰好一次后返回起点,求最短路径。</li>
|
||||
<li>最大团问题:给定一个无向图,找到最大的完全子图,即子图中的任意两个顶点之间都有边相连。</li>
|
||||
</ul>
|
||||
<p>请注意,对于许多组合优化问题,回溯都不是最优解决方案。</p>
|
||||
<p>请注意,对于许多组合优化问题,回溯不是最优解决方案。</p>
|
||||
<ul>
|
||||
<li>0-1 背包问题通常使用动态规划解决,以达到更高的时间效率。</li>
|
||||
<li>旅行商是一个著名的 NP-Hard 问题,常用解法有遗传算法和蚁群算法等。</li>
|
||||
<li>最大团问题是图论中的一个经典问题,可用贪心等启发式算法来解决。</li>
|
||||
<li>最大团问题是图论中的一个经典问题,可用贪心算法等启发式算法来解决。</li>
|
||||
</ul>
|
||||
|
||||
<!-- Source file information -->
|
||||
|
||||
@@ -3398,7 +3398,7 @@
|
||||
<h1 id="134-n">13.4 N 皇后问题<a class="headerlink" href="#134-n" title="Permanent link">¶</a></h1>
|
||||
<div class="admonition question">
|
||||
<p class="admonition-title">Question</p>
|
||||
<p>根据国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。给定 <span class="arithmatex">\(n\)</span> 个皇后和一个 <span class="arithmatex">\(n \times n\)</span> 大小的棋盘,寻找使得所有皇后之间无法相互攻击的摆放方案。</p>
|
||||
<p>根据国际象棋的规则,皇后可以攻击与同处一行、一列或一条斜线上的棋子。给定 <span class="arithmatex">\(n\)</span> 个皇后和一个 <span class="arithmatex">\(n \times n\)</span> 大小的棋盘,寻找使得所有皇后之间无法相互攻击的摆放方案。</p>
|
||||
</div>
|
||||
<p>如图 13-15 所示,当 <span class="arithmatex">\(n = 4\)</span> 时,共可以找到两个解。从回溯算法的角度看,<span class="arithmatex">\(n \times n\)</span> 大小的棋盘共有 <span class="arithmatex">\(n^2\)</span> 个格子,给出了所有的选择 <code>choices</code> 。在逐个放置皇后的过程中,棋盘状态在不断地变化,每个时刻的棋盘就是状态 <code>state</code> 。</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="4 皇后问题的解" class="animation-figure" src="../n_queens_problem.assets/solution_4_queens.png" /></a></p>
|
||||
@@ -3411,15 +3411,15 @@
|
||||
<h3 id="1">1. 逐行放置策略<a class="headerlink" href="#1" title="Permanent link">¶</a></h3>
|
||||
<p>皇后的数量和棋盘的行数都为 <span class="arithmatex">\(n\)</span> ,因此我们容易得到一个推论:<strong>棋盘每行都允许且只允许放置一个皇后</strong>。</p>
|
||||
<p>也就是说,我们可以采取逐行放置策略:从第一行开始,在每行放置一个皇后,直至最后一行结束。</p>
|
||||
<p>如图 13-17 所示,为 <span class="arithmatex">\(4\)</span> 皇后问题的逐行放置过程。受画幅限制,图 13-17 仅展开了第一行的其中一个搜索分支,并且将不满足列约束和对角线约束的方案都进行了剪枝。</p>
|
||||
<p>图 13-17 所示为 <span class="arithmatex">\(4\)</span> 皇后问题的逐行放置过程。受画幅限制,图 13-17 仅展开了第一行的其中一个搜索分支,并且将不满足列约束和对角线约束的方案都进行了剪枝。</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="逐行放置策略" class="animation-figure" src="../n_queens_problem.assets/n_queens_placing.png" /></a></p>
|
||||
<p align="center"> 图 13-17 逐行放置策略 </p>
|
||||
|
||||
<p>本质上看,<strong>逐行放置策略起到了剪枝的作用</strong>,它避免了同一行出现多个皇后的所有搜索分支。</p>
|
||||
<p>从本质上看,<strong>逐行放置策略起到了剪枝的作用</strong>,它避免了同一行出现多个皇后的所有搜索分支。</p>
|
||||
<h3 id="2">2. 列与对角线剪枝<a class="headerlink" href="#2" title="Permanent link">¶</a></h3>
|
||||
<p>为了满足列约束,我们可以利用一个长度为 <span class="arithmatex">\(n\)</span> 的布尔型数组 <code>cols</code> 记录每一列是否有皇后。在每次决定放置前,我们通过 <code>cols</code> 将已有皇后的列进行剪枝,并在回溯中动态更新 <code>cols</code> 的状态。</p>
|
||||
<p>那么,如何处理对角线约束呢?设棋盘中某个格子的行列索引为 <span class="arithmatex">\((row, col)\)</span> ,选定矩阵中的某条主对角线,我们发现该对角线上所有格子的行索引减列索引都相等,<strong>即对角线上所有格子的 <span class="arithmatex">\(row - col\)</span> 为恒定值</strong>。</p>
|
||||
<p>也就是说,如果两个格子满足 <span class="arithmatex">\(row_1 - col_1 = row_2 - col_2\)</span> ,则它们一定处在同一条主对角线上。利用该规律,我们可以借助图 13-18 所示的数组 <code>diags1</code> ,记录每条主对角线上是否有皇后。</p>
|
||||
<p>也就是说,如果两个格子满足 <span class="arithmatex">\(row_1 - col_1 = row_2 - col_2\)</span> ,则它们一定处在同一条主对角线上。利用该规律,我们可以借助图 13-18 所示的数组 <code>diags1</code> 记录每条主对角线上是否有皇后。</p>
|
||||
<p>同理,<strong>次对角线上的所有格子的 <span class="arithmatex">\(row + col\)</span> 是恒定值</strong>。我们同样也可以借助数组 <code>diags2</code> 来处理次对角线约束。</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="处理列约束和对角线约束" class="animation-figure" src="../n_queens_problem.assets/n_queens_cols_diagonals.png" /></a></p>
|
||||
<p align="center"> 图 13-18 处理列约束和对角线约束 </p>
|
||||
@@ -3448,7 +3448,7 @@
|
||||
<a id="__codelineno-0-17" name="__codelineno-0-17" href="#__codelineno-0-17"></a> <span class="c1"># 计算该格子对应的主对角线和副对角线</span>
|
||||
<a id="__codelineno-0-18" name="__codelineno-0-18" href="#__codelineno-0-18"></a> <span class="n">diag1</span> <span class="o">=</span> <span class="n">row</span> <span class="o">-</span> <span class="n">col</span> <span class="o">+</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<a id="__codelineno-0-19" name="__codelineno-0-19" href="#__codelineno-0-19"></a> <span class="n">diag2</span> <span class="o">=</span> <span class="n">row</span> <span class="o">+</span> <span class="n">col</span>
|
||||
<a id="__codelineno-0-20" name="__codelineno-0-20" href="#__codelineno-0-20"></a> <span class="c1"># 剪枝:不允许该格子所在列、主对角线、副对角线存在皇后</span>
|
||||
<a id="__codelineno-0-20" name="__codelineno-0-20" href="#__codelineno-0-20"></a> <span class="c1"># 剪枝:不允许该格子所在列、主对角线、副对角线上存在皇后</span>
|
||||
<a id="__codelineno-0-21" name="__codelineno-0-21" href="#__codelineno-0-21"></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">cols</span><span class="p">[</span><span class="n">col</span><span class="p">]</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">diags1</span><span class="p">[</span><span class="n">diag1</span><span class="p">]</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">diags2</span><span class="p">[</span><span class="n">diag2</span><span class="p">]:</span>
|
||||
<a id="__codelineno-0-22" name="__codelineno-0-22" href="#__codelineno-0-22"></a> <span class="c1"># 尝试:将皇后放置在该格子</span>
|
||||
<a id="__codelineno-0-23" name="__codelineno-0-23" href="#__codelineno-0-23"></a> <span class="n">state</span><span class="p">[</span><span class="n">row</span><span class="p">][</span><span class="n">col</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"Q"</span>
|
||||
@@ -3464,8 +3464,8 @@
|
||||
<a id="__codelineno-0-33" name="__codelineno-0-33" href="#__codelineno-0-33"></a> <span class="c1"># 初始化 n*n 大小的棋盘,其中 'Q' 代表皇后,'#' 代表空位</span>
|
||||
<a id="__codelineno-0-34" name="__codelineno-0-34" href="#__codelineno-0-34"></a> <span class="n">state</span> <span class="o">=</span> <span class="p">[[</span><span class="s2">"#"</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">)]</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">)]</span>
|
||||
<a id="__codelineno-0-35" name="__codelineno-0-35" href="#__codelineno-0-35"></a> <span class="n">cols</span> <span class="o">=</span> <span class="p">[</span><span class="kc">False</span><span class="p">]</span> <span class="o">*</span> <span class="n">n</span> <span class="c1"># 记录列是否有皇后</span>
|
||||
<a id="__codelineno-0-36" name="__codelineno-0-36" href="#__codelineno-0-36"></a> <span class="n">diags1</span> <span class="o">=</span> <span class="p">[</span><span class="kc">False</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="c1"># 记录主对角线是否有皇后</span>
|
||||
<a id="__codelineno-0-37" name="__codelineno-0-37" href="#__codelineno-0-37"></a> <span class="n">diags2</span> <span class="o">=</span> <span class="p">[</span><span class="kc">False</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="c1"># 记录副对角线是否有皇后</span>
|
||||
<a id="__codelineno-0-36" name="__codelineno-0-36" href="#__codelineno-0-36"></a> <span class="n">diags1</span> <span class="o">=</span> <span class="p">[</span><span class="kc">False</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="c1"># 记录主对角线上是否有皇后</span>
|
||||
<a id="__codelineno-0-37" name="__codelineno-0-37" href="#__codelineno-0-37"></a> <span class="n">diags2</span> <span class="o">=</span> <span class="p">[</span><span class="kc">False</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="c1"># 记录副对角线上是否有皇后</span>
|
||||
<a id="__codelineno-0-38" name="__codelineno-0-38" href="#__codelineno-0-38"></a> <span class="n">res</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<a id="__codelineno-0-39" name="__codelineno-0-39" href="#__codelineno-0-39"></a> <span class="n">backtrack</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">state</span><span class="p">,</span> <span class="n">res</span><span class="p">,</span> <span class="n">cols</span><span class="p">,</span> <span class="n">diags1</span><span class="p">,</span> <span class="n">diags2</span><span class="p">)</span>
|
||||
<a id="__codelineno-0-40" name="__codelineno-0-40" href="#__codelineno-0-40"></a>
|
||||
@@ -3486,7 +3486,7 @@
|
||||
<a id="__codelineno-1-11" name="__codelineno-1-11" href="#__codelineno-1-11"></a><span class="w"> </span><span class="c1">// 计算该格子对应的主对角线和副对角线</span>
|
||||
<a id="__codelineno-1-12" name="__codelineno-1-12" href="#__codelineno-1-12"></a><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">diag1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">row</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">col</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
|
||||
<a id="__codelineno-1-13" name="__codelineno-1-13" href="#__codelineno-1-13"></a><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">diag2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">row</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">col</span><span class="p">;</span>
|
||||
<a id="__codelineno-1-14" name="__codelineno-1-14" href="#__codelineno-1-14"></a><span class="w"> </span><span class="c1">// 剪枝:不允许该格子所在列、主对角线、副对角线存在皇后</span>
|
||||
<a id="__codelineno-1-14" name="__codelineno-1-14" href="#__codelineno-1-14"></a><span class="w"> </span><span class="c1">// 剪枝:不允许该格子所在列、主对角线、副对角线上存在皇后</span>
|
||||
<a id="__codelineno-1-15" name="__codelineno-1-15" href="#__codelineno-1-15"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">cols</span><span class="p">[</span><span class="n">col</span><span class="p">]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="o">!</span><span class="n">diags1</span><span class="p">[</span><span class="n">diag1</span><span class="p">]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="o">!</span><span class="n">diags2</span><span class="p">[</span><span class="n">diag2</span><span class="p">])</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-1-16" name="__codelineno-1-16" href="#__codelineno-1-16"></a><span class="w"> </span><span class="c1">// 尝试:将皇后放置在该格子</span>
|
||||
<a id="__codelineno-1-17" name="__codelineno-1-17" href="#__codelineno-1-17"></a><span class="w"> </span><span class="n">state</span><span class="p">[</span><span class="n">row</span><span class="p">][</span><span class="n">col</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"Q"</span><span class="p">;</span>
|
||||
@@ -3505,8 +3505,8 @@
|
||||
<a id="__codelineno-1-30" name="__codelineno-1-30" href="#__codelineno-1-30"></a><span class="w"> </span><span class="c1">// 初始化 n*n 大小的棋盘,其中 'Q' 代表皇后,'#' 代表空位</span>
|
||||
<a id="__codelineno-1-31" name="__codelineno-1-31" href="#__codelineno-1-31"></a><span class="w"> </span><span class="n">vector</span><span class="o"><</span><span class="n">vector</span><span class="o"><</span><span class="n">string</span><span class="o">>></span><span class="w"> </span><span class="n">state</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="n">vector</span><span class="o"><</span><span class="n">string</span><span class="o">></span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="s">"#"</span><span class="p">));</span>
|
||||
<a id="__codelineno-1-32" name="__codelineno-1-32" href="#__codelineno-1-32"></a><span class="w"> </span><span class="n">vector</span><span class="o"><</span><span class="kt">bool</span><span class="o">></span><span class="w"> </span><span class="n">cols</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="nb">false</span><span class="p">);</span><span class="w"> </span><span class="c1">// 记录列是否有皇后</span>
|
||||
<a id="__codelineno-1-33" name="__codelineno-1-33" href="#__codelineno-1-33"></a><span class="w"> </span><span class="n">vector</span><span class="o"><</span><span class="kt">bool</span><span class="o">></span><span class="w"> </span><span class="n">diags1</span><span class="p">(</span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="nb">false</span><span class="p">);</span><span class="w"> </span><span class="c1">// 记录主对角线是否有皇后</span>
|
||||
<a id="__codelineno-1-34" name="__codelineno-1-34" href="#__codelineno-1-34"></a><span class="w"> </span><span class="n">vector</span><span class="o"><</span><span class="kt">bool</span><span class="o">></span><span class="w"> </span><span class="n">diags2</span><span class="p">(</span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="nb">false</span><span class="p">);</span><span class="w"> </span><span class="c1">// 记录副对角线是否有皇后</span>
|
||||
<a id="__codelineno-1-33" name="__codelineno-1-33" href="#__codelineno-1-33"></a><span class="w"> </span><span class="n">vector</span><span class="o"><</span><span class="kt">bool</span><span class="o">></span><span class="w"> </span><span class="n">diags1</span><span class="p">(</span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="nb">false</span><span class="p">);</span><span class="w"> </span><span class="c1">// 记录主对角线上是否有皇后</span>
|
||||
<a id="__codelineno-1-34" name="__codelineno-1-34" href="#__codelineno-1-34"></a><span class="w"> </span><span class="n">vector</span><span class="o"><</span><span class="kt">bool</span><span class="o">></span><span class="w"> </span><span class="n">diags2</span><span class="p">(</span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="nb">false</span><span class="p">);</span><span class="w"> </span><span class="c1">// 记录副对角线上是否有皇后</span>
|
||||
<a id="__codelineno-1-35" name="__codelineno-1-35" href="#__codelineno-1-35"></a><span class="w"> </span><span class="n">vector</span><span class="o"><</span><span class="n">vector</span><span class="o"><</span><span class="n">vector</span><span class="o"><</span><span class="n">string</span><span class="o">>>></span><span class="w"> </span><span class="n">res</span><span class="p">;</span>
|
||||
<a id="__codelineno-1-36" name="__codelineno-1-36" href="#__codelineno-1-36"></a>
|
||||
<a id="__codelineno-1-37" name="__codelineno-1-37" href="#__codelineno-1-37"></a><span class="w"> </span><span class="n">backtrack</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="n">state</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">cols</span><span class="p">,</span><span class="w"> </span><span class="n">diags1</span><span class="p">,</span><span class="w"> </span><span class="n">diags2</span><span class="p">);</span>
|
||||
@@ -3533,7 +3533,7 @@
|
||||
<a id="__codelineno-2-15" name="__codelineno-2-15" href="#__codelineno-2-15"></a><span class="w"> </span><span class="c1">// 计算该格子对应的主对角线和副对角线</span>
|
||||
<a id="__codelineno-2-16" name="__codelineno-2-16" href="#__codelineno-2-16"></a><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">diag1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">row</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">col</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
|
||||
<a id="__codelineno-2-17" name="__codelineno-2-17" href="#__codelineno-2-17"></a><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">diag2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">row</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">col</span><span class="p">;</span>
|
||||
<a id="__codelineno-2-18" name="__codelineno-2-18" href="#__codelineno-2-18"></a><span class="w"> </span><span class="c1">// 剪枝:不允许该格子所在列、主对角线、副对角线存在皇后</span>
|
||||
<a id="__codelineno-2-18" name="__codelineno-2-18" href="#__codelineno-2-18"></a><span class="w"> </span><span class="c1">// 剪枝:不允许该格子所在列、主对角线、副对角线上存在皇后</span>
|
||||
<a id="__codelineno-2-19" name="__codelineno-2-19" href="#__codelineno-2-19"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">cols</span><span class="o">[</span><span class="n">col</span><span class="o">]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="o">!</span><span class="n">diags1</span><span class="o">[</span><span class="n">diag1</span><span class="o">]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="o">!</span><span class="n">diags2</span><span class="o">[</span><span class="n">diag2</span><span class="o">]</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-2-20" name="__codelineno-2-20" href="#__codelineno-2-20"></a><span class="w"> </span><span class="c1">// 尝试:将皇后放置在该格子</span>
|
||||
<a id="__codelineno-2-21" name="__codelineno-2-21" href="#__codelineno-2-21"></a><span class="w"> </span><span class="n">state</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="n">row</span><span class="p">).</span><span class="na">set</span><span class="p">(</span><span class="n">col</span><span class="p">,</span><span class="w"> </span><span class="s">"Q"</span><span class="p">);</span>
|
||||
@@ -3559,8 +3559,8 @@
|
||||
<a id="__codelineno-2-41" name="__codelineno-2-41" href="#__codelineno-2-41"></a><span class="w"> </span><span class="n">state</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">row</span><span class="p">);</span>
|
||||
<a id="__codelineno-2-42" name="__codelineno-2-42" href="#__codelineno-2-42"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-2-43" name="__codelineno-2-43" href="#__codelineno-2-43"></a><span class="w"> </span><span class="kt">boolean</span><span class="o">[]</span><span class="w"> </span><span class="n">cols</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">boolean</span><span class="o">[</span><span class="n">n</span><span class="o">]</span><span class="p">;</span><span class="w"> </span><span class="c1">// 记录列是否有皇后</span>
|
||||
<a id="__codelineno-2-44" name="__codelineno-2-44" href="#__codelineno-2-44"></a><span class="w"> </span><span class="kt">boolean</span><span class="o">[]</span><span class="w"> </span><span class="n">diags1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">boolean</span><span class="o">[</span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="o">]</span><span class="p">;</span><span class="w"> </span><span class="c1">// 记录主对角线是否有皇后</span>
|
||||
<a id="__codelineno-2-45" name="__codelineno-2-45" href="#__codelineno-2-45"></a><span class="w"> </span><span class="kt">boolean</span><span class="o">[]</span><span class="w"> </span><span class="n">diags2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">boolean</span><span class="o">[</span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="o">]</span><span class="p">;</span><span class="w"> </span><span class="c1">// 记录副对角线是否有皇后</span>
|
||||
<a id="__codelineno-2-44" name="__codelineno-2-44" href="#__codelineno-2-44"></a><span class="w"> </span><span class="kt">boolean</span><span class="o">[]</span><span class="w"> </span><span class="n">diags1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">boolean</span><span class="o">[</span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="o">]</span><span class="p">;</span><span class="w"> </span><span class="c1">// 记录主对角线上是否有皇后</span>
|
||||
<a id="__codelineno-2-45" name="__codelineno-2-45" href="#__codelineno-2-45"></a><span class="w"> </span><span class="kt">boolean</span><span class="o">[]</span><span class="w"> </span><span class="n">diags2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">boolean</span><span class="o">[</span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="o">]</span><span class="p">;</span><span class="w"> </span><span class="c1">// 记录副对角线上是否有皇后</span>
|
||||
<a id="__codelineno-2-46" name="__codelineno-2-46" href="#__codelineno-2-46"></a><span class="w"> </span><span class="n">List</span><span class="o"><</span><span class="n">List</span><span class="o"><</span><span class="n">List</span><span class="o"><</span><span class="n">String</span><span class="o">>>></span><span class="w"> </span><span class="n">res</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ArrayList</span><span class="o"><></span><span class="p">();</span>
|
||||
<a id="__codelineno-2-47" name="__codelineno-2-47" href="#__codelineno-2-47"></a>
|
||||
<a id="__codelineno-2-48" name="__codelineno-2-48" href="#__codelineno-2-48"></a><span class="w"> </span><span class="n">backtrack</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="n">state</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">cols</span><span class="p">,</span><span class="w"> </span><span class="n">diags1</span><span class="p">,</span><span class="w"> </span><span class="n">diags2</span><span class="p">);</span>
|
||||
@@ -3587,7 +3587,7 @@
|
||||
<a id="__codelineno-3-15" name="__codelineno-3-15" href="#__codelineno-3-15"></a><span class="w"> </span><span class="c1">// 计算该格子对应的主对角线和副对角线</span>
|
||||
<a id="__codelineno-3-16" name="__codelineno-3-16" href="#__codelineno-3-16"></a><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">diag1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">row</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">col</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">1</span><span class="p">;</span>
|
||||
<a id="__codelineno-3-17" name="__codelineno-3-17" href="#__codelineno-3-17"></a><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">diag2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">row</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">col</span><span class="p">;</span>
|
||||
<a id="__codelineno-3-18" name="__codelineno-3-18" href="#__codelineno-3-18"></a><span class="w"> </span><span class="c1">// 剪枝:不允许该格子所在列、主对角线、副对角线存在皇后</span>
|
||||
<a id="__codelineno-3-18" name="__codelineno-3-18" href="#__codelineno-3-18"></a><span class="w"> </span><span class="c1">// 剪枝:不允许该格子所在列、主对角线、副对角线上存在皇后</span>
|
||||
<a id="__codelineno-3-19" name="__codelineno-3-19" href="#__codelineno-3-19"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">cols</span><span class="p">[</span><span class="n">col</span><span class="p">]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="o">!</span><span class="n">diags1</span><span class="p">[</span><span class="n">diag1</span><span class="p">]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="o">!</span><span class="n">diags2</span><span class="p">[</span><span class="n">diag2</span><span class="p">])</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-3-20" name="__codelineno-3-20" href="#__codelineno-3-20"></a><span class="w"> </span><span class="c1">// 尝试:将皇后放置在该格子</span>
|
||||
<a id="__codelineno-3-21" name="__codelineno-3-21" href="#__codelineno-3-21"></a><span class="w"> </span><span class="n">state</span><span class="p">[</span><span class="n">row</span><span class="p">][</span><span class="n">col</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"Q"</span><span class="p">;</span>
|
||||
@@ -3613,8 +3613,8 @@
|
||||
<a id="__codelineno-3-41" name="__codelineno-3-41" href="#__codelineno-3-41"></a><span class="w"> </span><span class="n">state</span><span class="p">.</span><span class="n">Add</span><span class="p">(</span><span class="n">row</span><span class="p">);</span>
|
||||
<a id="__codelineno-3-42" name="__codelineno-3-42" href="#__codelineno-3-42"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-3-43" name="__codelineno-3-43" href="#__codelineno-3-43"></a><span class="w"> </span><span class="kt">bool</span><span class="p">[]</span><span class="w"> </span><span class="n">cols</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">bool</span><span class="p">[</span><span class="n">n</span><span class="p">];</span><span class="w"> </span><span class="c1">// 记录列是否有皇后</span>
|
||||
<a id="__codelineno-3-44" name="__codelineno-3-44" href="#__codelineno-3-44"></a><span class="w"> </span><span class="kt">bool</span><span class="p">[]</span><span class="w"> </span><span class="n">diags1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">bool</span><span class="p">[</span><span class="m">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">1</span><span class="p">];</span><span class="w"> </span><span class="c1">// 记录主对角线是否有皇后</span>
|
||||
<a id="__codelineno-3-45" name="__codelineno-3-45" href="#__codelineno-3-45"></a><span class="w"> </span><span class="kt">bool</span><span class="p">[]</span><span class="w"> </span><span class="n">diags2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">bool</span><span class="p">[</span><span class="m">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">1</span><span class="p">];</span><span class="w"> </span><span class="c1">// 记录副对角线是否有皇后</span>
|
||||
<a id="__codelineno-3-44" name="__codelineno-3-44" href="#__codelineno-3-44"></a><span class="w"> </span><span class="kt">bool</span><span class="p">[]</span><span class="w"> </span><span class="n">diags1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">bool</span><span class="p">[</span><span class="m">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">1</span><span class="p">];</span><span class="w"> </span><span class="c1">// 记录主对角线上是否有皇后</span>
|
||||
<a id="__codelineno-3-45" name="__codelineno-3-45" href="#__codelineno-3-45"></a><span class="w"> </span><span class="kt">bool</span><span class="p">[]</span><span class="w"> </span><span class="n">diags2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">bool</span><span class="p">[</span><span class="m">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">1</span><span class="p">];</span><span class="w"> </span><span class="c1">// 记录副对角线上是否有皇后</span>
|
||||
<a id="__codelineno-3-46" name="__codelineno-3-46" href="#__codelineno-3-46"></a><span class="w"> </span><span class="n">List</span><span class="o"><</span><span class="n">List</span><span class="o"><</span><span class="n">List</span><span class="o"><</span><span class="kt">string</span><span class="o">>>></span><span class="w"> </span><span class="n">res</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>
|
||||
<a id="__codelineno-3-47" name="__codelineno-3-47" href="#__codelineno-3-47"></a>
|
||||
<a id="__codelineno-3-48" name="__codelineno-3-48" href="#__codelineno-3-48"></a><span class="w"> </span><span class="n">Backtrack</span><span class="p">(</span><span class="m">0</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="n">state</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">cols</span><span class="p">,</span><span class="w"> </span><span class="n">diags1</span><span class="p">,</span><span class="w"> </span><span class="n">diags2</span><span class="p">);</span>
|
||||
@@ -3641,7 +3641,7 @@
|
||||
<a id="__codelineno-4-15" name="__codelineno-4-15" href="#__codelineno-4-15"></a><span class="w"> </span><span class="c1">// 计算该格子对应的主对角线和副对角线</span>
|
||||
<a id="__codelineno-4-16" name="__codelineno-4-16" href="#__codelineno-4-16"></a><span class="w"> </span><span class="nx">diag1</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">row</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">col</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span>
|
||||
<a id="__codelineno-4-17" name="__codelineno-4-17" href="#__codelineno-4-17"></a><span class="w"> </span><span class="nx">diag2</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">row</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">col</span>
|
||||
<a id="__codelineno-4-18" name="__codelineno-4-18" href="#__codelineno-4-18"></a><span class="w"> </span><span class="c1">// 剪枝:不允许该格子所在列、主对角线、副对角线存在皇后</span>
|
||||
<a id="__codelineno-4-18" name="__codelineno-4-18" href="#__codelineno-4-18"></a><span class="w"> </span><span class="c1">// 剪枝:不允许该格子所在列、主对角线、副对角线上存在皇后</span>
|
||||
<a id="__codelineno-4-19" name="__codelineno-4-19" href="#__codelineno-4-19"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">!(</span><span class="o">*</span><span class="nx">cols</span><span class="p">)[</span><span class="nx">col</span><span class="p">]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">!(</span><span class="o">*</span><span class="nx">diags1</span><span class="p">)[</span><span class="nx">diag1</span><span class="p">]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">!(</span><span class="o">*</span><span class="nx">diags2</span><span class="p">)[</span><span class="nx">diag2</span><span class="p">]</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-4-20" name="__codelineno-4-20" href="#__codelineno-4-20"></a><span class="w"> </span><span class="c1">// 尝试:将皇后放置在该格子</span>
|
||||
<a id="__codelineno-4-21" name="__codelineno-4-21" href="#__codelineno-4-21"></a><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="nx">state</span><span class="p">)[</span><span class="nx">row</span><span class="p">][</span><span class="nx">col</span><span class="p">]</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s">"Q"</span>
|
||||
@@ -3672,7 +3672,7 @@
|
||||
<a id="__codelineno-4-46" name="__codelineno-4-46" href="#__codelineno-4-46"></a><span class="w"> </span><span class="c1">// 计算该格子对应的主对角线和副对角线</span>
|
||||
<a id="__codelineno-4-47" name="__codelineno-4-47" href="#__codelineno-4-47"></a><span class="w"> </span><span class="nx">diag1</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">row</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">col</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span>
|
||||
<a id="__codelineno-4-48" name="__codelineno-4-48" href="#__codelineno-4-48"></a><span class="w"> </span><span class="nx">diag2</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">row</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">col</span>
|
||||
<a id="__codelineno-4-49" name="__codelineno-4-49" href="#__codelineno-4-49"></a><span class="w"> </span><span class="c1">// 剪枝:不允许该格子所在列、主对角线、副对角线存在皇后</span>
|
||||
<a id="__codelineno-4-49" name="__codelineno-4-49" href="#__codelineno-4-49"></a><span class="w"> </span><span class="c1">// 剪枝:不允许该格子所在列、主对角线、副对角线上存在皇后</span>
|
||||
<a id="__codelineno-4-50" name="__codelineno-4-50" href="#__codelineno-4-50"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">!(</span><span class="o">*</span><span class="nx">cols</span><span class="p">)[</span><span class="nx">col</span><span class="p">]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">!(</span><span class="o">*</span><span class="nx">diags1</span><span class="p">)[</span><span class="nx">diag1</span><span class="p">]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">!(</span><span class="o">*</span><span class="nx">diags2</span><span class="p">)[</span><span class="nx">diag2</span><span class="p">]</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-4-51" name="__codelineno-4-51" href="#__codelineno-4-51"></a><span class="w"> </span><span class="c1">// 尝试:将皇后放置在该格子</span>
|
||||
<a id="__codelineno-4-52" name="__codelineno-4-52" href="#__codelineno-4-52"></a><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="nx">state</span><span class="p">)[</span><span class="nx">row</span><span class="p">][</span><span class="nx">col</span><span class="p">]</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s">"Q"</span>
|
||||
@@ -3719,7 +3719,7 @@
|
||||
<a id="__codelineno-5-10" name="__codelineno-5-10" href="#__codelineno-5-10"></a> <span class="c1">// 计算该格子对应的主对角线和副对角线</span>
|
||||
<a id="__codelineno-5-11" name="__codelineno-5-11" href="#__codelineno-5-11"></a> <span class="kd">let</span> <span class="nv">diag1</span> <span class="p">=</span> <span class="n">row</span> <span class="o">-</span> <span class="n">col</span> <span class="o">+</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<a id="__codelineno-5-12" name="__codelineno-5-12" href="#__codelineno-5-12"></a> <span class="kd">let</span> <span class="nv">diag2</span> <span class="p">=</span> <span class="n">row</span> <span class="o">+</span> <span class="n">col</span>
|
||||
<a id="__codelineno-5-13" name="__codelineno-5-13" href="#__codelineno-5-13"></a> <span class="c1">// 剪枝:不允许该格子所在列、主对角线、副对角线存在皇后</span>
|
||||
<a id="__codelineno-5-13" name="__codelineno-5-13" href="#__codelineno-5-13"></a> <span class="c1">// 剪枝:不允许该格子所在列、主对角线、副对角线上存在皇后</span>
|
||||
<a id="__codelineno-5-14" name="__codelineno-5-14" href="#__codelineno-5-14"></a> <span class="k">if</span> <span class="o">!</span><span class="n">cols</span><span class="p">[</span><span class="n">col</span><span class="p">]</span> <span class="o">&&</span> <span class="o">!</span><span class="n">diags1</span><span class="p">[</span><span class="n">diag1</span><span class="p">]</span> <span class="o">&&</span> <span class="o">!</span><span class="n">diags2</span><span class="p">[</span><span class="n">diag2</span><span class="p">]</span> <span class="p">{</span>
|
||||
<a id="__codelineno-5-15" name="__codelineno-5-15" href="#__codelineno-5-15"></a> <span class="c1">// 尝试:将皇后放置在该格子</span>
|
||||
<a id="__codelineno-5-16" name="__codelineno-5-16" href="#__codelineno-5-16"></a> <span class="n">state</span><span class="p">[</span><span class="n">row</span><span class="p">][</span><span class="n">col</span><span class="p">]</span> <span class="p">=</span> <span class="s">"Q"</span>
|
||||
@@ -3742,8 +3742,8 @@
|
||||
<a id="__codelineno-5-33" name="__codelineno-5-33" href="#__codelineno-5-33"></a> <span class="c1">// 初始化 n*n 大小的棋盘,其中 'Q' 代表皇后,'#' 代表空位</span>
|
||||
<a id="__codelineno-5-34" name="__codelineno-5-34" href="#__codelineno-5-34"></a> <span class="kd">var</span> <span class="nv">state</span> <span class="p">=</span> <span class="nb">Array</span><span class="p">(</span><span class="n">repeating</span><span class="p">:</span> <span class="nb">Array</span><span class="p">(</span><span class="n">repeating</span><span class="p">:</span> <span class="s">"#"</span><span class="p">,</span> <span class="bp">count</span><span class="p">:</span> <span class="n">n</span><span class="p">),</span> <span class="bp">count</span><span class="p">:</span> <span class="n">n</span><span class="p">)</span>
|
||||
<a id="__codelineno-5-35" name="__codelineno-5-35" href="#__codelineno-5-35"></a> <span class="kd">var</span> <span class="nv">cols</span> <span class="p">=</span> <span class="nb">Array</span><span class="p">(</span><span class="n">repeating</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span> <span class="bp">count</span><span class="p">:</span> <span class="n">n</span><span class="p">)</span> <span class="c1">// 记录列是否有皇后</span>
|
||||
<a id="__codelineno-5-36" name="__codelineno-5-36" href="#__codelineno-5-36"></a> <span class="kd">var</span> <span class="nv">diags1</span> <span class="p">=</span> <span class="nb">Array</span><span class="p">(</span><span class="n">repeating</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span> <span class="bp">count</span><span class="p">:</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="c1">// 记录主对角线是否有皇后</span>
|
||||
<a id="__codelineno-5-37" name="__codelineno-5-37" href="#__codelineno-5-37"></a> <span class="kd">var</span> <span class="nv">diags2</span> <span class="p">=</span> <span class="nb">Array</span><span class="p">(</span><span class="n">repeating</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span> <span class="bp">count</span><span class="p">:</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="c1">// 记录副对角线是否有皇后</span>
|
||||
<a id="__codelineno-5-36" name="__codelineno-5-36" href="#__codelineno-5-36"></a> <span class="kd">var</span> <span class="nv">diags1</span> <span class="p">=</span> <span class="nb">Array</span><span class="p">(</span><span class="n">repeating</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span> <span class="bp">count</span><span class="p">:</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="c1">// 记录主对角线上是否有皇后</span>
|
||||
<a id="__codelineno-5-37" name="__codelineno-5-37" href="#__codelineno-5-37"></a> <span class="kd">var</span> <span class="nv">diags2</span> <span class="p">=</span> <span class="nb">Array</span><span class="p">(</span><span class="n">repeating</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span> <span class="bp">count</span><span class="p">:</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="c1">// 记录副对角线上是否有皇后</span>
|
||||
<a id="__codelineno-5-38" name="__codelineno-5-38" href="#__codelineno-5-38"></a> <span class="kd">var</span> <span class="nv">res</span><span class="p">:</span> <span class="p">[[[</span><span class="nb">String</span><span class="p">]]]</span> <span class="p">=</span> <span class="p">[]</span>
|
||||
<a id="__codelineno-5-39" name="__codelineno-5-39" href="#__codelineno-5-39"></a>
|
||||
<a id="__codelineno-5-40" name="__codelineno-5-40" href="#__codelineno-5-40"></a> <span class="n">backtrack</span><span class="p">(</span><span class="n">row</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span><span class="p">,</span> <span class="n">state</span><span class="p">:</span> <span class="p">&</span><span class="n">state</span><span class="p">,</span> <span class="n">res</span><span class="p">:</span> <span class="p">&</span><span class="n">res</span><span class="p">,</span> <span class="n">cols</span><span class="p">:</span> <span class="p">&</span><span class="n">cols</span><span class="p">,</span> <span class="n">diags1</span><span class="p">:</span> <span class="p">&</span><span class="n">diags1</span><span class="p">,</span> <span class="n">diags2</span><span class="p">:</span> <span class="p">&</span><span class="n">diags2</span><span class="p">)</span>
|
||||
@@ -3765,7 +3765,7 @@
|
||||
<a id="__codelineno-6-10" name="__codelineno-6-10" href="#__codelineno-6-10"></a><span class="w"> </span><span class="c1">// 计算该格子对应的主对角线和副对角线</span>
|
||||
<a id="__codelineno-6-11" name="__codelineno-6-11" href="#__codelineno-6-11"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">diag1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">row</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">col</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">;</span>
|
||||
<a id="__codelineno-6-12" name="__codelineno-6-12" href="#__codelineno-6-12"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">diag2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">row</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">col</span><span class="p">;</span>
|
||||
<a id="__codelineno-6-13" name="__codelineno-6-13" href="#__codelineno-6-13"></a><span class="w"> </span><span class="c1">// 剪枝:不允许该格子所在列、主对角线、副对角线存在皇后</span>
|
||||
<a id="__codelineno-6-13" name="__codelineno-6-13" href="#__codelineno-6-13"></a><span class="w"> </span><span class="c1">// 剪枝:不允许该格子所在列、主对角线、副对角线上存在皇后</span>
|
||||
<a id="__codelineno-6-14" name="__codelineno-6-14" href="#__codelineno-6-14"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="nx">cols</span><span class="p">[</span><span class="nx">col</span><span class="p">]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="o">!</span><span class="nx">diags1</span><span class="p">[</span><span class="nx">diag1</span><span class="p">]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="o">!</span><span class="nx">diags2</span><span class="p">[</span><span class="nx">diag2</span><span class="p">])</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-6-15" name="__codelineno-6-15" href="#__codelineno-6-15"></a><span class="w"> </span><span class="c1">// 尝试:将皇后放置在该格子</span>
|
||||
<a id="__codelineno-6-16" name="__codelineno-6-16" href="#__codelineno-6-16"></a><span class="w"> </span><span class="nx">state</span><span class="p">[</span><span class="nx">row</span><span class="p">][</span><span class="nx">col</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'Q'</span><span class="p">;</span>
|
||||
@@ -3784,8 +3784,8 @@
|
||||
<a id="__codelineno-6-29" name="__codelineno-6-29" href="#__codelineno-6-29"></a><span class="w"> </span><span class="c1">// 初始化 n*n 大小的棋盘,其中 'Q' 代表皇后,'#' 代表空位</span>
|
||||
<a id="__codelineno-6-30" name="__codelineno-6-30" href="#__codelineno-6-30"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">state</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Array</span><span class="p">.</span><span class="kr">from</span><span class="p">({</span><span class="w"> </span><span class="nx">length</span><span class="o">:</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="nx">n</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="s1">'#'</span><span class="p">));</span>
|
||||
<a id="__codelineno-6-31" name="__codelineno-6-31" href="#__codelineno-6-31"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">cols</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="nx">n</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="kc">false</span><span class="p">);</span><span class="w"> </span><span class="c1">// 记录列是否有皇后</span>
|
||||
<a id="__codelineno-6-32" name="__codelineno-6-32" href="#__codelineno-6-32"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">diags1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="kc">false</span><span class="p">);</span><span class="w"> </span><span class="c1">// 记录主对角线是否有皇后</span>
|
||||
<a id="__codelineno-6-33" name="__codelineno-6-33" href="#__codelineno-6-33"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">diags2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="kc">false</span><span class="p">);</span><span class="w"> </span><span class="c1">// 记录副对角线是否有皇后</span>
|
||||
<a id="__codelineno-6-32" name="__codelineno-6-32" href="#__codelineno-6-32"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">diags1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="kc">false</span><span class="p">);</span><span class="w"> </span><span class="c1">// 记录主对角线上是否有皇后</span>
|
||||
<a id="__codelineno-6-33" name="__codelineno-6-33" href="#__codelineno-6-33"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">diags2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="kc">false</span><span class="p">);</span><span class="w"> </span><span class="c1">// 记录副对角线上是否有皇后</span>
|
||||
<a id="__codelineno-6-34" name="__codelineno-6-34" href="#__codelineno-6-34"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">res</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>
|
||||
<a id="__codelineno-6-35" name="__codelineno-6-35" href="#__codelineno-6-35"></a>
|
||||
<a id="__codelineno-6-36" name="__codelineno-6-36" href="#__codelineno-6-36"></a><span class="w"> </span><span class="nx">backtrack</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">n</span><span class="p">,</span><span class="w"> </span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">res</span><span class="p">,</span><span class="w"> </span><span class="nx">cols</span><span class="p">,</span><span class="w"> </span><span class="nx">diags1</span><span class="p">,</span><span class="w"> </span><span class="nx">diags2</span><span class="p">);</span>
|
||||
@@ -3814,7 +3814,7 @@
|
||||
<a id="__codelineno-7-18" name="__codelineno-7-18" href="#__codelineno-7-18"></a><span class="w"> </span><span class="c1">// 计算该格子对应的主对角线和副对角线</span>
|
||||
<a id="__codelineno-7-19" name="__codelineno-7-19" href="#__codelineno-7-19"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">diag1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">row</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">col</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">;</span>
|
||||
<a id="__codelineno-7-20" name="__codelineno-7-20" href="#__codelineno-7-20"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">diag2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">row</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">col</span><span class="p">;</span>
|
||||
<a id="__codelineno-7-21" name="__codelineno-7-21" href="#__codelineno-7-21"></a><span class="w"> </span><span class="c1">// 剪枝:不允许该格子所在列、主对角线、副对角线存在皇后</span>
|
||||
<a id="__codelineno-7-21" name="__codelineno-7-21" href="#__codelineno-7-21"></a><span class="w"> </span><span class="c1">// 剪枝:不允许该格子所在列、主对角线、副对角线上存在皇后</span>
|
||||
<a id="__codelineno-7-22" name="__codelineno-7-22" href="#__codelineno-7-22"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="nx">cols</span><span class="p">[</span><span class="nx">col</span><span class="p">]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="o">!</span><span class="nx">diags1</span><span class="p">[</span><span class="nx">diag1</span><span class="p">]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="o">!</span><span class="nx">diags2</span><span class="p">[</span><span class="nx">diag2</span><span class="p">])</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-7-23" name="__codelineno-7-23" href="#__codelineno-7-23"></a><span class="w"> </span><span class="c1">// 尝试:将皇后放置在该格子</span>
|
||||
<a id="__codelineno-7-24" name="__codelineno-7-24" href="#__codelineno-7-24"></a><span class="w"> </span><span class="nx">state</span><span class="p">[</span><span class="nx">row</span><span class="p">][</span><span class="nx">col</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'Q'</span><span class="p">;</span>
|
||||
@@ -3833,8 +3833,8 @@
|
||||
<a id="__codelineno-7-37" name="__codelineno-7-37" href="#__codelineno-7-37"></a><span class="w"> </span><span class="c1">// 初始化 n*n 大小的棋盘,其中 'Q' 代表皇后,'#' 代表空位</span>
|
||||
<a id="__codelineno-7-38" name="__codelineno-7-38" href="#__codelineno-7-38"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">state</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Array</span><span class="p">.</span><span class="kr">from</span><span class="p">({</span><span class="w"> </span><span class="nx">length</span><span class="o">:</span><span class="w"> </span><span class="kt">n</span><span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="nx">n</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="s1">'#'</span><span class="p">));</span>
|
||||
<a id="__codelineno-7-39" name="__codelineno-7-39" href="#__codelineno-7-39"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">cols</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="nx">n</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="kc">false</span><span class="p">);</span><span class="w"> </span><span class="c1">// 记录列是否有皇后</span>
|
||||
<a id="__codelineno-7-40" name="__codelineno-7-40" href="#__codelineno-7-40"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">diags1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="kc">false</span><span class="p">);</span><span class="w"> </span><span class="c1">// 记录主对角线是否有皇后</span>
|
||||
<a id="__codelineno-7-41" name="__codelineno-7-41" href="#__codelineno-7-41"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">diags2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="kc">false</span><span class="p">);</span><span class="w"> </span><span class="c1">// 记录副对角线是否有皇后</span>
|
||||
<a id="__codelineno-7-40" name="__codelineno-7-40" href="#__codelineno-7-40"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">diags1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="kc">false</span><span class="p">);</span><span class="w"> </span><span class="c1">// 记录主对角线上是否有皇后</span>
|
||||
<a id="__codelineno-7-41" name="__codelineno-7-41" href="#__codelineno-7-41"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">diags2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="kc">false</span><span class="p">);</span><span class="w"> </span><span class="c1">// 记录副对角线上是否有皇后</span>
|
||||
<a id="__codelineno-7-42" name="__codelineno-7-42" href="#__codelineno-7-42"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">res</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[][][]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>
|
||||
<a id="__codelineno-7-43" name="__codelineno-7-43" href="#__codelineno-7-43"></a>
|
||||
<a id="__codelineno-7-44" name="__codelineno-7-44" href="#__codelineno-7-44"></a><span class="w"> </span><span class="nx">backtrack</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">n</span><span class="p">,</span><span class="w"> </span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">res</span><span class="p">,</span><span class="w"> </span><span class="nx">cols</span><span class="p">,</span><span class="w"> </span><span class="nx">diags1</span><span class="p">,</span><span class="w"> </span><span class="nx">diags2</span><span class="p">);</span>
|
||||
@@ -3867,7 +3867,7 @@
|
||||
<a id="__codelineno-8-22" name="__codelineno-8-22" href="#__codelineno-8-22"></a><span class="w"> </span><span class="c1">// 计算该格子对应的主对角线和副对角线</span>
|
||||
<a id="__codelineno-8-23" name="__codelineno-8-23" href="#__codelineno-8-23"></a><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">diag1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">row</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">col</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">1</span><span class="p">;</span>
|
||||
<a id="__codelineno-8-24" name="__codelineno-8-24" href="#__codelineno-8-24"></a><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">diag2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">row</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">col</span><span class="p">;</span>
|
||||
<a id="__codelineno-8-25" name="__codelineno-8-25" href="#__codelineno-8-25"></a><span class="w"> </span><span class="c1">// 剪枝:不允许该格子所在列、主对角线、副对角线存在皇后</span>
|
||||
<a id="__codelineno-8-25" name="__codelineno-8-25" href="#__codelineno-8-25"></a><span class="w"> </span><span class="c1">// 剪枝:不允许该格子所在列、主对角线、副对角线上存在皇后</span>
|
||||
<a id="__codelineno-8-26" name="__codelineno-8-26" href="#__codelineno-8-26"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">cols</span><span class="p">[</span><span class="n">col</span><span class="p">]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="o">!</span><span class="n">diags1</span><span class="p">[</span><span class="n">diag1</span><span class="p">]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="o">!</span><span class="n">diags2</span><span class="p">[</span><span class="n">diag2</span><span class="p">])</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-8-27" name="__codelineno-8-27" href="#__codelineno-8-27"></a><span class="w"> </span><span class="c1">// 尝试:将皇后放置在该格子</span>
|
||||
<a id="__codelineno-8-28" name="__codelineno-8-28" href="#__codelineno-8-28"></a><span class="w"> </span><span class="n">state</span><span class="p">[</span><span class="n">row</span><span class="p">][</span><span class="n">col</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"Q"</span><span class="p">;</span>
|
||||
@@ -3890,8 +3890,8 @@
|
||||
<a id="__codelineno-8-45" name="__codelineno-8-45" href="#__codelineno-8-45"></a><span class="w"> </span><span class="c1">// 初始化 n*n 大小的棋盘,其中 'Q' 代表皇后,'#' 代表空位</span>
|
||||
<a id="__codelineno-8-46" name="__codelineno-8-46" href="#__codelineno-8-46"></a><span class="w"> </span><span class="n">List</span><span class="o"><</span><span class="n">List</span><span class="o"><</span><span class="kt">String</span><span class="o">>></span><span class="w"> </span><span class="n">state</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">List</span><span class="p">.</span><span class="n">generate</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="n">index</span><span class="p">)</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="n">List</span><span class="p">.</span><span class="n">filled</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="s2">"#"</span><span class="p">));</span>
|
||||
<a id="__codelineno-8-47" name="__codelineno-8-47" href="#__codelineno-8-47"></a><span class="w"> </span><span class="n">List</span><span class="o"><</span><span class="kt">bool</span><span class="o">></span><span class="w"> </span><span class="n">cols</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">List</span><span class="p">.</span><span class="n">filled</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="kc">false</span><span class="p">);</span><span class="w"> </span><span class="c1">// 记录列是否有皇后</span>
|
||||
<a id="__codelineno-8-48" name="__codelineno-8-48" href="#__codelineno-8-48"></a><span class="w"> </span><span class="n">List</span><span class="o"><</span><span class="kt">bool</span><span class="o">></span><span class="w"> </span><span class="n">diags1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">List</span><span class="p">.</span><span class="n">filled</span><span class="p">(</span><span class="m">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">1</span><span class="p">,</span><span class="w"> </span><span class="kc">false</span><span class="p">);</span><span class="w"> </span><span class="c1">// 记录主对角线是否有皇后</span>
|
||||
<a id="__codelineno-8-49" name="__codelineno-8-49" href="#__codelineno-8-49"></a><span class="w"> </span><span class="n">List</span><span class="o"><</span><span class="kt">bool</span><span class="o">></span><span class="w"> </span><span class="n">diags2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">List</span><span class="p">.</span><span class="n">filled</span><span class="p">(</span><span class="m">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">1</span><span class="p">,</span><span class="w"> </span><span class="kc">false</span><span class="p">);</span><span class="w"> </span><span class="c1">// 记录副对角线是否有皇后</span>
|
||||
<a id="__codelineno-8-48" name="__codelineno-8-48" href="#__codelineno-8-48"></a><span class="w"> </span><span class="n">List</span><span class="o"><</span><span class="kt">bool</span><span class="o">></span><span class="w"> </span><span class="n">diags1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">List</span><span class="p">.</span><span class="n">filled</span><span class="p">(</span><span class="m">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">1</span><span class="p">,</span><span class="w"> </span><span class="kc">false</span><span class="p">);</span><span class="w"> </span><span class="c1">// 记录主对角线上是否有皇后</span>
|
||||
<a id="__codelineno-8-49" name="__codelineno-8-49" href="#__codelineno-8-49"></a><span class="w"> </span><span class="n">List</span><span class="o"><</span><span class="kt">bool</span><span class="o">></span><span class="w"> </span><span class="n">diags2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">List</span><span class="p">.</span><span class="n">filled</span><span class="p">(</span><span class="m">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">1</span><span class="p">,</span><span class="w"> </span><span class="kc">false</span><span class="p">);</span><span class="w"> </span><span class="c1">// 记录副对角线上是否有皇后</span>
|
||||
<a id="__codelineno-8-50" name="__codelineno-8-50" href="#__codelineno-8-50"></a><span class="w"> </span><span class="n">List</span><span class="o"><</span><span class="n">List</span><span class="o"><</span><span class="n">List</span><span class="o"><</span><span class="kt">String</span><span class="o">>>></span><span class="w"> </span><span class="n">res</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>
|
||||
<a id="__codelineno-8-51" name="__codelineno-8-51" href="#__codelineno-8-51"></a>
|
||||
<a id="__codelineno-8-52" name="__codelineno-8-52" href="#__codelineno-8-52"></a><span class="w"> </span><span class="n">backtrack</span><span class="p">(</span><span class="m">0</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="n">state</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">cols</span><span class="p">,</span><span class="w"> </span><span class="n">diags1</span><span class="p">,</span><span class="w"> </span><span class="n">diags2</span><span class="p">);</span>
|
||||
@@ -3918,7 +3918,7 @@
|
||||
<a id="__codelineno-9-15" name="__codelineno-9-15" href="#__codelineno-9-15"></a><span class="w"> </span><span class="c1">// 计算该格子对应的主对角线和副对角线</span>
|
||||
<a id="__codelineno-9-16" name="__codelineno-9-16" href="#__codelineno-9-16"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">diag1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">row</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">col</span><span class="p">;</span>
|
||||
<a id="__codelineno-9-17" name="__codelineno-9-17" href="#__codelineno-9-17"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">diag2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">row</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">col</span><span class="p">;</span>
|
||||
<a id="__codelineno-9-18" name="__codelineno-9-18" href="#__codelineno-9-18"></a><span class="w"> </span><span class="c1">// 剪枝:不允许该格子所在列、主对角线、副对角线存在皇后</span>
|
||||
<a id="__codelineno-9-18" name="__codelineno-9-18" href="#__codelineno-9-18"></a><span class="w"> </span><span class="c1">// 剪枝:不允许该格子所在列、主对角线、副对角线上存在皇后</span>
|
||||
<a id="__codelineno-9-19" name="__codelineno-9-19" href="#__codelineno-9-19"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="o">!</span><span class="n">cols</span><span class="p">[</span><span class="n">col</span><span class="p">]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="o">!</span><span class="n">diags1</span><span class="p">[</span><span class="n">diag1</span><span class="p">]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="o">!</span><span class="n">diags2</span><span class="p">[</span><span class="n">diag2</span><span class="p">]</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-9-20" name="__codelineno-9-20" href="#__codelineno-9-20"></a><span class="w"> </span><span class="c1">// 尝试:将皇后放置在该格子</span>
|
||||
<a id="__codelineno-9-21" name="__codelineno-9-21" href="#__codelineno-9-21"></a><span class="w"> </span><span class="n">state</span><span class="p">.</span><span class="n">get_mut</span><span class="p">(</span><span class="n">row</span><span class="p">).</span><span class="n">unwrap</span><span class="p">()[</span><span class="n">col</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"Q"</span><span class="p">.</span><span class="n">into</span><span class="p">();</span>
|
||||
@@ -3944,8 +3944,8 @@
|
||||
<a id="__codelineno-9-41" name="__codelineno-9-41" href="#__codelineno-9-41"></a><span class="w"> </span><span class="n">state</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">row</span><span class="p">);</span>
|
||||
<a id="__codelineno-9-42" name="__codelineno-9-42" href="#__codelineno-9-42"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-9-43" name="__codelineno-9-43" href="#__codelineno-9-43"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">cols</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="fm">vec!</span><span class="p">[</span><span class="kc">false</span><span class="p">;</span><span class="w"> </span><span class="n">n</span><span class="p">];</span><span class="w"> </span><span class="c1">// 记录列是否有皇后</span>
|
||||
<a id="__codelineno-9-44" name="__codelineno-9-44" href="#__codelineno-9-44"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">diags1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="fm">vec!</span><span class="p">[</span><span class="kc">false</span><span class="p">;</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">];</span><span class="w"> </span><span class="c1">// 记录主对角线是否有皇后</span>
|
||||
<a id="__codelineno-9-45" name="__codelineno-9-45" href="#__codelineno-9-45"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">diags2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="fm">vec!</span><span class="p">[</span><span class="kc">false</span><span class="p">;</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">];</span><span class="w"> </span><span class="c1">// 记录副对角线是否有皇后</span>
|
||||
<a id="__codelineno-9-44" name="__codelineno-9-44" href="#__codelineno-9-44"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">diags1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="fm">vec!</span><span class="p">[</span><span class="kc">false</span><span class="p">;</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">];</span><span class="w"> </span><span class="c1">// 记录主对角线上是否有皇后</span>
|
||||
<a id="__codelineno-9-45" name="__codelineno-9-45" href="#__codelineno-9-45"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">diags2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="fm">vec!</span><span class="p">[</span><span class="kc">false</span><span class="p">;</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">];</span><span class="w"> </span><span class="c1">// 记录副对角线上是否有皇后</span>
|
||||
<a id="__codelineno-9-46" name="__codelineno-9-46" href="#__codelineno-9-46"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">res</span>: <span class="nb">Vec</span><span class="o"><</span><span class="nb">Vec</span><span class="o"><</span><span class="nb">Vec</span><span class="o"><</span><span class="nb">String</span><span class="o">>>></span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Vec</span>::<span class="n">new</span><span class="p">();</span>
|
||||
<a id="__codelineno-9-47" name="__codelineno-9-47" href="#__codelineno-9-47"></a>
|
||||
<a id="__codelineno-9-48" name="__codelineno-9-48" href="#__codelineno-9-48"></a><span class="w"> </span><span class="n">backtrack</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="k">mut</span><span class="w"> </span><span class="n">state</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="k">mut</span><span class="w"> </span><span class="n">res</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="k">mut</span><span class="w"> </span><span class="n">cols</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="k">mut</span><span class="w"> </span><span class="n">diags1</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="k">mut</span><span class="w"> </span><span class="n">diags2</span><span class="p">);</span>
|
||||
@@ -3973,7 +3973,7 @@
|
||||
<a id="__codelineno-10-16" name="__codelineno-10-16" href="#__codelineno-10-16"></a><span class="w"> </span><span class="c1">// 计算该格子对应的主对角线和副对角线</span>
|
||||
<a id="__codelineno-10-17" name="__codelineno-10-17" href="#__codelineno-10-17"></a><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">diag1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">row</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">col</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
|
||||
<a id="__codelineno-10-18" name="__codelineno-10-18" href="#__codelineno-10-18"></a><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">diag2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">row</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">col</span><span class="p">;</span>
|
||||
<a id="__codelineno-10-19" name="__codelineno-10-19" href="#__codelineno-10-19"></a><span class="w"> </span><span class="c1">// 剪枝:不允许该格子所在列、主对角线、副对角线存在皇后</span>
|
||||
<a id="__codelineno-10-19" name="__codelineno-10-19" href="#__codelineno-10-19"></a><span class="w"> </span><span class="c1">// 剪枝:不允许该格子所在列、主对角线、副对角线上存在皇后</span>
|
||||
<a id="__codelineno-10-20" name="__codelineno-10-20" href="#__codelineno-10-20"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">cols</span><span class="p">[</span><span class="n">col</span><span class="p">]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="o">!</span><span class="n">diags1</span><span class="p">[</span><span class="n">diag1</span><span class="p">]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="o">!</span><span class="n">diags2</span><span class="p">[</span><span class="n">diag2</span><span class="p">])</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-10-21" name="__codelineno-10-21" href="#__codelineno-10-21"></a><span class="w"> </span><span class="c1">// 尝试:将皇后放置在该格子</span>
|
||||
<a id="__codelineno-10-22" name="__codelineno-10-22" href="#__codelineno-10-22"></a><span class="w"> </span><span class="n">state</span><span class="p">[</span><span class="n">row</span><span class="p">][</span><span class="n">col</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="sc">'Q'</span><span class="p">;</span>
|
||||
@@ -3998,8 +3998,8 @@
|
||||
<a id="__codelineno-10-41" name="__codelineno-10-41" href="#__codelineno-10-41"></a><span class="w"> </span><span class="n">state</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">n</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="sc">'\0'</span><span class="p">;</span>
|
||||
<a id="__codelineno-10-42" name="__codelineno-10-42" href="#__codelineno-10-42"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-10-43" name="__codelineno-10-43" href="#__codelineno-10-43"></a><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">cols</span><span class="p">[</span><span class="n">MAX_SIZE</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="nb">false</span><span class="p">};</span><span class="w"> </span><span class="c1">// 记录列是否有皇后</span>
|
||||
<a id="__codelineno-10-44" name="__codelineno-10-44" href="#__codelineno-10-44"></a><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">diags1</span><span class="p">[</span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">MAX_SIZE</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="nb">false</span><span class="p">};</span><span class="w"> </span><span class="c1">// 记录主对角线是否有皇后</span>
|
||||
<a id="__codelineno-10-45" name="__codelineno-10-45" href="#__codelineno-10-45"></a><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">diags2</span><span class="p">[</span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">MAX_SIZE</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="nb">false</span><span class="p">};</span><span class="w"> </span><span class="c1">// 记录副对角线是否有皇后</span>
|
||||
<a id="__codelineno-10-44" name="__codelineno-10-44" href="#__codelineno-10-44"></a><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">diags1</span><span class="p">[</span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">MAX_SIZE</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="nb">false</span><span class="p">};</span><span class="w"> </span><span class="c1">// 记录主对角线上是否有皇后</span>
|
||||
<a id="__codelineno-10-45" name="__codelineno-10-45" href="#__codelineno-10-45"></a><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">diags2</span><span class="p">[</span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">MAX_SIZE</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="nb">false</span><span class="p">};</span><span class="w"> </span><span class="c1">// 记录副对角线上是否有皇后</span>
|
||||
<a id="__codelineno-10-46" name="__codelineno-10-46" href="#__codelineno-10-46"></a>
|
||||
<a id="__codelineno-10-47" name="__codelineno-10-47" href="#__codelineno-10-47"></a><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">***</span><span class="n">res</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">char</span><span class="w"> </span><span class="o">***</span><span class="p">)</span><span class="n">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="kt">char</span><span class="w"> </span><span class="o">**</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">MAX_SIZE</span><span class="p">);</span>
|
||||
<a id="__codelineno-10-48" name="__codelineno-10-48" href="#__codelineno-10-48"></a><span class="w"> </span><span class="o">*</span><span class="n">returnSize</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
|
||||
@@ -4016,7 +4016,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>逐行放置 <span class="arithmatex">\(n\)</span> 次,考虑列约束,则从第一行到最后一行分别有 <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> 个选择,<strong>因此时间复杂度为 <span class="arithmatex">\(O(n!)\)</span></strong> 。实际上,根据对角线约束的剪枝也能够大幅地缩小搜索空间,因而搜索效率往往优于以上时间复杂度。</p>
|
||||
<p>逐行放置 <span class="arithmatex">\(n\)</span> 次,考虑列约束,则从第一行到最后一行分别有 <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> 个选择,<strong>因此时间复杂度为 <span class="arithmatex">\(O(n!)\)</span></strong> 。实际上,根据对角线约束的剪枝也能够大幅缩小搜索空间,因而搜索效率往往优于以上时间复杂度。</p>
|
||||
<p>数组 <code>state</code> 使用 <span class="arithmatex">\(O(n^2)\)</span> 空间,数组 <code>cols</code>、<code>diags1</code> 和 <code>diags2</code> 皆使用 <span class="arithmatex">\(O(n)\)</span> 空间。最大递归深度为 <span class="arithmatex">\(n\)</span> ,使用 <span class="arithmatex">\(O(n)\)</span> 栈帧空间。因此,<strong>空间复杂度为 <span class="arithmatex">\(O(n^2)\)</span></strong> 。</p>
|
||||
|
||||
<!-- Source file information -->
|
||||
|
||||
@@ -3476,7 +3476,7 @@
|
||||
|
||||
<!-- Page content -->
|
||||
<h1 id="132">13.2 全排列问题<a class="headerlink" href="#132" title="Permanent link">¶</a></h1>
|
||||
<p>全排列问题是回溯算法的一个典型应用。它的定义是在给定一个集合(如一个数组或字符串)的情况下,找出这个集合中元素的所有可能的排列。</p>
|
||||
<p>全排列问题是回溯算法的一个典型应用。它的定义是在给定一个集合(如一个数组或字符串)的情况下,找出其中元素的所有可能的排列。</p>
|
||||
<p>表 13-2 列举了几个示例数据,包括输入数组和对应的所有排列。</p>
|
||||
<p align="center"> 表 13-2 全排列示例 </p>
|
||||
|
||||
@@ -3507,11 +3507,11 @@
|
||||
<h2 id="1321">13.2.1 无相等元素的情况<a class="headerlink" href="#1321" title="Permanent link">¶</a></h2>
|
||||
<div class="admonition question">
|
||||
<p class="admonition-title">Question</p>
|
||||
<p>输入一个整数数组,数组中不包含重复元素,返回所有可能的排列。</p>
|
||||
<p>输入一个整数数组,其中不包含重复元素,返回所有可能的排列。</p>
|
||||
</div>
|
||||
<p>从回溯算法的角度看,<strong>我们可以把生成排列的过程想象成一系列选择的结果</strong>。假设输入数组为 <span class="arithmatex">\([1, 2, 3]\)</span> ,如果我们先选择 <span class="arithmatex">\(1\)</span>、再选择 <span class="arithmatex">\(3\)</span>、最后选择 <span class="arithmatex">\(2\)</span> ,则获得排列 <span class="arithmatex">\([1, 3, 2]\)</span> 。回退表示撤销一个选择,之后继续尝试其他选择。</p>
|
||||
<p>从回溯算法的角度看,<strong>我们可以把生成排列的过程想象成一系列选择的结果</strong>。假设输入数组为 <span class="arithmatex">\([1, 2, 3]\)</span> ,如果我们先选择 <span class="arithmatex">\(1\)</span> ,再选择 <span class="arithmatex">\(3\)</span> ,最后选择 <span class="arithmatex">\(2\)</span> ,则获得排列 <span class="arithmatex">\([1, 3, 2]\)</span> 。回退表示撤销一个选择,之后继续尝试其他选择。</p>
|
||||
<p>从回溯代码的角度看,候选集合 <code>choices</code> 是输入数组中的所有元素,状态 <code>state</code> 是直至目前已被选择的元素。请注意,每个元素只允许被选择一次,<strong>因此 <code>state</code> 中的所有元素都应该是唯一的</strong>。</p>
|
||||
<p>如图 13-5 所示,我们可以将搜索过程展开成一个递归树,树中的每个节点代表当前状态 <code>state</code> 。从根节点开始,经过三轮选择后到达叶节点,每个叶节点都对应一个排列。</p>
|
||||
<p>如图 13-5 所示,我们可以将搜索过程展开成一棵递归树,树中的每个节点代表当前状态 <code>state</code> 。从根节点开始,经过三轮选择后到达叶节点,每个叶节点都对应一个排列。</p>
|
||||
<p><a class="glightbox" href="../permutations_problem.assets/permutations_i.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="全排列的递归树" class="animation-figure" src="../permutations_problem.assets/permutations_i.png" /></a></p>
|
||||
<p align="center"> 图 13-5 全排列的递归树 </p>
|
||||
|
||||
@@ -3519,15 +3519,15 @@
|
||||
<p>为了实现每个元素只被选择一次,我们考虑引入一个布尔型数组 <code>selected</code> ,其中 <code>selected[i]</code> 表示 <code>choices[i]</code> 是否已被选择,并基于它实现以下剪枝操作。</p>
|
||||
<ul>
|
||||
<li>在做出选择 <code>choice[i]</code> 后,我们就将 <code>selected[i]</code> 赋值为 <span class="arithmatex">\(\text{True}\)</span> ,代表它已被选择。</li>
|
||||
<li>遍历选择列表 <code>choices</code> 时,跳过所有已被选择过的节点,即剪枝。</li>
|
||||
<li>遍历选择列表 <code>choices</code> 时,跳过所有已被选择的节点,即剪枝。</li>
|
||||
</ul>
|
||||
<p>如图 13-6 所示,假设我们第一轮选择 1 ,第二轮选择 3 ,第三轮选择 2 ,则需要在第二轮剪掉元素 1 的分支,在第三轮剪掉元素 1 和元素 3 的分支。</p>
|
||||
<p><a class="glightbox" href="../permutations_problem.assets/permutations_i_pruning.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="全排列剪枝示例" class="animation-figure" src="../permutations_problem.assets/permutations_i_pruning.png" /></a></p>
|
||||
<p align="center"> 图 13-6 全排列剪枝示例 </p>
|
||||
|
||||
<p>观察图 13-6 发现,该剪枝操作将搜索空间大小从 <span class="arithmatex">\(O(n^n)\)</span> 降低至 <span class="arithmatex">\(O(n!)\)</span> 。</p>
|
||||
<p>观察图 13-6 发现,该剪枝操作将搜索空间大小从 <span class="arithmatex">\(O(n^n)\)</span> 减小至 <span class="arithmatex">\(O(n!)\)</span> 。</p>
|
||||
<h3 id="2">2. 代码实现<a class="headerlink" href="#2" title="Permanent link">¶</a></h3>
|
||||
<p>想清楚以上信息之后,我们就可以在框架代码中做“完形填空”了。为了缩短代码行数,我们不单独实现框架代码中的各个函数,而是将他们展开在 <code>backtrack()</code> 函数中。</p>
|
||||
<p>想清楚以上信息之后,我们就可以在框架代码中做“完形填空”了。为了缩短整体代码,我们不单独实现框架代码中的各个函数,而是将它们展开在 <code>backtrack()</code> 函数中:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="1:12"><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" /><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">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
@@ -3930,20 +3930,20 @@
|
||||
<p>输入一个整数数组,<strong>数组中可能包含重复元素</strong>,返回所有不重复的排列。</p>
|
||||
</div>
|
||||
<p>假设输入数组为 <span class="arithmatex">\([1, 1, 2]\)</span> 。为了方便区分两个重复元素 <span class="arithmatex">\(1\)</span> ,我们将第二个 <span class="arithmatex">\(1\)</span> 记为 <span class="arithmatex">\(\hat{1}\)</span> 。</p>
|
||||
<p>如图 13-7 所示,上述方法生成的排列有一半都是重复的。</p>
|
||||
<p>如图 13-7 所示,上述方法生成的排列有一半是重复的。</p>
|
||||
<p><a class="glightbox" href="../permutations_problem.assets/permutations_ii.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="重复排列" class="animation-figure" src="../permutations_problem.assets/permutations_ii.png" /></a></p>
|
||||
<p align="center"> 图 13-7 重复排列 </p>
|
||||
|
||||
<p>那么如何去除重复的排列呢?最直接地,考虑借助一个哈希表,直接对排列结果进行去重。然而这样做不够优雅,<strong>因为生成重复排列的搜索分支是没有必要的,应当被提前识别并剪枝</strong>,这样可以进一步提升算法效率。</p>
|
||||
<p>那么如何去除重复的排列呢?最直接地,考虑借助一个哈希表,直接对排列结果进行去重。然而这样做不够优雅,<strong>因为生成重复排列的搜索分支没有必要,应当提前识别并剪枝</strong>,这样可以进一步提升算法效率。</p>
|
||||
<h3 id="1_1">1. 相等元素剪枝<a class="headerlink" href="#1_1" title="Permanent link">¶</a></h3>
|
||||
<p>观察图 13-8 ,在第一轮中,选择 <span class="arithmatex">\(1\)</span> 或选择 <span class="arithmatex">\(\hat{1}\)</span> 是等价的,在这两个选择之下生成的所有排列都是重复的。因此应该把 <span class="arithmatex">\(\hat{1}\)</span> 剪枝掉。</p>
|
||||
<p>观察图 13-8 ,在第一轮中,选择 <span class="arithmatex">\(1\)</span> 或选择 <span class="arithmatex">\(\hat{1}\)</span> 是等价的,在这两个选择之下生成的所有排列都是重复的。因此应该把 <span class="arithmatex">\(\hat{1}\)</span> 剪枝。</p>
|
||||
<p>同理,在第一轮选择 <span class="arithmatex">\(2\)</span> 之后,第二轮选择中的 <span class="arithmatex">\(1\)</span> 和 <span class="arithmatex">\(\hat{1}\)</span> 也会产生重复分支,因此也应将第二轮的 <span class="arithmatex">\(\hat{1}\)</span> 剪枝。</p>
|
||||
<p>本质上看,<strong>我们的目标是在某一轮选择中,保证多个相等的元素仅被选择一次</strong>。</p>
|
||||
<p>从本质上看,<strong>我们的目标是在某一轮选择中,保证多个相等的元素仅被选择一次</strong>。</p>
|
||||
<p><a class="glightbox" href="../permutations_problem.assets/permutations_ii_pruning.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="重复排列剪枝" class="animation-figure" src="../permutations_problem.assets/permutations_ii_pruning.png" /></a></p>
|
||||
<p align="center"> 图 13-8 重复排列剪枝 </p>
|
||||
|
||||
<h3 id="2_1">2. 代码实现<a class="headerlink" href="#2_1" title="Permanent link">¶</a></h3>
|
||||
<p>在上一题的代码的基础上,我们考虑在每一轮选择中开启一个哈希表 <code>duplicated</code> ,用于记录该轮中已经尝试过的元素,并将重复元素剪枝。</p>
|
||||
<p>在上一题的代码的基础上,我们考虑在每一轮选择中开启一个哈希表 <code>duplicated</code> ,用于记录该轮中已经尝试过的元素,并将重复元素剪枝:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="2:12"><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" /><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">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
@@ -4366,10 +4366,10 @@
|
||||
<p>假设元素两两之间互不相同,则 <span class="arithmatex">\(n\)</span> 个元素共有 <span class="arithmatex">\(n!\)</span> 种排列(阶乘);在记录结果时,需要复制长度为 <span class="arithmatex">\(n\)</span> 的列表,使用 <span class="arithmatex">\(O(n)\)</span> 时间。<strong>因此时间复杂度为 <span class="arithmatex">\(O(n!n)\)</span></strong> 。</p>
|
||||
<p>最大递归深度为 <span class="arithmatex">\(n\)</span> ,使用 <span class="arithmatex">\(O(n)\)</span> 栈帧空间。<code>selected</code> 使用 <span class="arithmatex">\(O(n)\)</span> 空间。同一时刻最多共有 <span class="arithmatex">\(n\)</span> 个 <code>duplicated</code> ,使用 <span class="arithmatex">\(O(n^2)\)</span> 空间。<strong>因此空间复杂度为 <span class="arithmatex">\(O(n^2)\)</span></strong> 。</p>
|
||||
<h3 id="3">3. 两种剪枝对比<a class="headerlink" href="#3" title="Permanent link">¶</a></h3>
|
||||
<p>请注意,虽然 <code>selected</code> 和 <code>duplicated</code> 都用作剪枝,但两者的目标是不同的。</p>
|
||||
<p>请注意,虽然 <code>selected</code> 和 <code>duplicated</code> 都用于剪枝,但两者的目标不同。</p>
|
||||
<ul>
|
||||
<li><strong>重复选择剪枝</strong>:整个搜索过程中只有一个 <code>selected</code> 。它记录的是当前状态中包含哪些元素,作用是防止 <code>choices</code> 中的任一元素在 <code>state</code> 中重复出现。</li>
|
||||
<li><strong>相等元素剪枝</strong>:每轮选择(即每个调用的 <code>backtrack</code> 函数)都包含一个 <code>duplicated</code> 。它记录的是在本轮遍历(即 <code>for</code> 循环)中哪些元素已被选择过,作用是保证相等的元素只被选择一次。</li>
|
||||
<li><strong>重复选择剪枝</strong>:整个搜索过程中只有一个 <code>selected</code> 。它记录的是当前状态中包含哪些元素,其作用是防止 <code>choices</code> 中的任一元素在 <code>state</code> 中重复出现。</li>
|
||||
<li><strong>相等元素剪枝</strong>:每轮选择(每个调用的 <code>backtrack</code> 函数)都包含一个 <code>duplicated</code> 。它记录的是在本轮遍历(<code>for</code> 循环)中哪些元素已被选择过,其作用是保证相等的元素只被选择一次。</li>
|
||||
</ul>
|
||||
<p>图 13-9 展示了两个剪枝条件的生效范围。注意,树中的每个节点代表一个选择,从根节点到叶节点的路径上的各个节点构成一个排列。</p>
|
||||
<p><a class="glightbox" href="../permutations_problem.assets/permutations_ii_pruning_summary.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="两种剪枝条件的作用范围" class="animation-figure" src="../permutations_problem.assets/permutations_ii_pruning_summary.png" /></a></p>
|
||||
|
||||
@@ -3484,11 +3484,11 @@
|
||||
<p>例如,输入集合 <span class="arithmatex">\(\{3, 4, 5\}\)</span> 和目标整数 <span class="arithmatex">\(9\)</span> ,解为 <span class="arithmatex">\(\{3, 3, 3\}, \{4, 5\}\)</span> 。需要注意以下两点。</p>
|
||||
<ul>
|
||||
<li>输入集合中的元素可以被无限次重复选取。</li>
|
||||
<li>子集是不区分元素顺序的,比如 <span class="arithmatex">\(\{4, 5\}\)</span> 和 <span class="arithmatex">\(\{5, 4\}\)</span> 是同一个子集。</li>
|
||||
<li>子集不区分元素顺序,比如 <span class="arithmatex">\(\{4, 5\}\)</span> 和 <span class="arithmatex">\(\{5, 4\}\)</span> 是同一个子集。</li>
|
||||
</ul>
|
||||
<h3 id="1">1. 参考全排列解法<a class="headerlink" href="#1" title="Permanent link">¶</a></h3>
|
||||
<p>类似于全排列问题,我们可以把子集的生成过程想象成一系列选择的结果,并在选择过程中实时更新“元素和”,当元素和等于 <code>target</code> 时,就将子集记录至结果列表。</p>
|
||||
<p>而与全排列问题不同的是,<strong>本题集合中的元素可以被无限次选取</strong>,因此无须借助 <code>selected</code> 布尔列表来记录元素是否已被选择。我们可以对全排列代码进行小幅修改,初步得到解题代码。</p>
|
||||
<p>而与全排列问题不同的是,<strong>本题集合中的元素可以被无限次选取</strong>,因此无须借助 <code>selected</code> 布尔列表来记录元素是否已被选择。我们可以对全排列代码进行小幅修改,初步得到解题代码:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="1:12"><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" /><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">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
@@ -3877,7 +3877,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<p>向以上代码输入数组 <span class="arithmatex">\([3, 4, 5]\)</span> 和目标元素 <span class="arithmatex">\(9\)</span> ,输出结果为 <span class="arithmatex">\([3, 3, 3], [4, 5], [5, 4]\)</span> 。<strong>虽然成功找出了所有和为 <span class="arithmatex">\(9\)</span> 的子集,但其中存在重复的子集 <span class="arithmatex">\([4, 5]\)</span> 和 <span class="arithmatex">\([5, 4]\)</span></strong> 。</p>
|
||||
<p>这是因为搜索过程是区分选择顺序的,然而子集不区分选择顺序。如图 13-10 所示,先选 <span class="arithmatex">\(4\)</span> 后选 <span class="arithmatex">\(5\)</span> 与先选 <span class="arithmatex">\(5\)</span> 后选 <span class="arithmatex">\(4\)</span> 是两个不同的分支,但两者对应同一个子集。</p>
|
||||
<p>这是因为搜索过程是区分选择顺序的,然而子集不区分选择顺序。如图 13-10 所示,先选 <span class="arithmatex">\(4\)</span> 后选 <span class="arithmatex">\(5\)</span> 与先选 <span class="arithmatex">\(5\)</span> 后选 <span class="arithmatex">\(4\)</span> 是不同的分支,但对应同一个子集。</p>
|
||||
<p><a class="glightbox" href="../subset_sum_problem.assets/subset_sum_i_naive.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="子集搜索与越界剪枝" class="animation-figure" src="../subset_sum_problem.assets/subset_sum_i_naive.png" /></a></p>
|
||||
<p align="center"> 图 13-10 子集搜索与越界剪枝 </p>
|
||||
|
||||
@@ -3890,23 +3890,23 @@
|
||||
<p><strong>我们考虑在搜索过程中通过剪枝进行去重</strong>。观察图 13-11 ,重复子集是在以不同顺序选择数组元素时产生的,例如以下情况。</p>
|
||||
<ol>
|
||||
<li>当第一轮和第二轮分别选择 <span class="arithmatex">\(3\)</span> 和 <span class="arithmatex">\(4\)</span> 时,会生成包含这两个元素的所有子集,记为 <span class="arithmatex">\([3, 4, \dots]\)</span> 。</li>
|
||||
<li>之后,当第一轮选择 <span class="arithmatex">\(4\)</span> 时,<strong>则第二轮应该跳过 <span class="arithmatex">\(3\)</span></strong> ,因为该选择产生的子集 <span class="arithmatex">\([4, 3, \dots]\)</span> 和 <code>1.</code> 中生成的子集完全重复。</li>
|
||||
<li>之后,当第一轮选择 <span class="arithmatex">\(4\)</span> 时,<strong>则第二轮应该跳过 <span class="arithmatex">\(3\)</span></strong> ,因为该选择产生的子集 <span class="arithmatex">\([4, 3, \dots]\)</span> 和第 <code>1.</code> 步中生成的子集完全重复。</li>
|
||||
</ol>
|
||||
<p>在搜索中,每一层的选择都是从左到右被逐个尝试的,因此越靠右的分支被剪掉的越多。</p>
|
||||
<p>在搜索过程中,每一层的选择都是从左到右被逐个尝试的,因此越靠右的分支被剪掉的越多。</p>
|
||||
<ol>
|
||||
<li>前两轮选择 <span class="arithmatex">\(3\)</span> 和 <span class="arithmatex">\(5\)</span> ,生成子集 <span class="arithmatex">\([3, 5, \dots]\)</span> 。</li>
|
||||
<li>前两轮选择 <span class="arithmatex">\(4\)</span> 和 <span class="arithmatex">\(5\)</span> ,生成子集 <span class="arithmatex">\([4, 5, \dots]\)</span> 。</li>
|
||||
<li>若第一轮选择 <span class="arithmatex">\(5\)</span> ,<strong>则第二轮应该跳过 <span class="arithmatex">\(3\)</span> 和 <span class="arithmatex">\(4\)</span></strong> ,因为子集 <span class="arithmatex">\([5, 3, \dots]\)</span> 和 <span class="arithmatex">\([5, 4, \dots]\)</span> 与第 <code>1.</code> 和 <code>2.</code> 步中描述的子集完全重复。</li>
|
||||
<li>若第一轮选择 <span class="arithmatex">\(5\)</span> ,<strong>则第二轮应该跳过 <span class="arithmatex">\(3\)</span> 和 <span class="arithmatex">\(4\)</span></strong> ,因为子集 <span class="arithmatex">\([5, 3, \dots]\)</span> 和 <span class="arithmatex">\([5, 4, \dots]\)</span> 与第 <code>1.</code> 步和第 <code>2.</code> 步中描述的子集完全重复。</li>
|
||||
</ol>
|
||||
<p><a class="glightbox" href="../subset_sum_problem.assets/subset_sum_i_pruning.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="不同选择顺序导致的重复子集" class="animation-figure" src="../subset_sum_problem.assets/subset_sum_i_pruning.png" /></a></p>
|
||||
<p align="center"> 图 13-11 不同选择顺序导致的重复子集 </p>
|
||||
|
||||
<p>总结来看,给定输入数组 <span class="arithmatex">\([x_1, x_2, \dots, x_n]\)</span> ,设搜索过程中的选择序列为 <span class="arithmatex">\([x_{i_1}, x_{i_2}, \dots, x_{i_m}]\)</span> ,则该选择序列需要满足 <span class="arithmatex">\(i_1 \leq i_2 \leq \dots \leq i_m\)</span> ,<strong>不满足该条件的选择序列都会造成重复,应当剪枝</strong>。</p>
|
||||
<h3 id="3">3. 代码实现<a class="headerlink" href="#3" title="Permanent link">¶</a></h3>
|
||||
<p>为实现该剪枝,我们初始化变量 <code>start</code> ,用于指示遍历起点。<strong>当做出选择 <span class="arithmatex">\(x_{i}\)</span> 后,设定下一轮从索引 <span class="arithmatex">\(i\)</span> 开始遍历</strong>。这样做就可以让选择序列满足 <span class="arithmatex">\(i_1 \leq i_2 \leq \dots \leq i_m\)</span> ,从而保证子集唯一。</p>
|
||||
<p>为实现该剪枝,我们初始化变量 <code>start</code> ,用于指示遍历起始点。<strong>当做出选择 <span class="arithmatex">\(x_{i}\)</span> 后,设定下一轮从索引 <span class="arithmatex">\(i\)</span> 开始遍历</strong>。这样做就可以让选择序列满足 <span class="arithmatex">\(i_1 \leq i_2 \leq \dots \leq i_m\)</span> ,从而保证子集唯一。</p>
|
||||
<p>除此之外,我们还对代码进行了以下两项优化。</p>
|
||||
<ul>
|
||||
<li>在开启搜索前,先将数组 <code>nums</code> 排序。在遍历所有选择时,<strong>当子集和超过 <code>target</code> 时直接结束循环</strong>,因为后边的元素更大,其子集和都一定会超过 <code>target</code> 。</li>
|
||||
<li>在开启搜索前,先将数组 <code>nums</code> 排序。在遍历所有选择时,<strong>当子集和超过 <code>target</code> 时直接结束循环</strong>,因为后边的元素更大,其子集和一定超过 <code>target</code> 。</li>
|
||||
<li>省去元素和变量 <code>total</code> ,<strong>通过在 <code>target</code> 上执行减法来统计元素和</strong>,当 <code>target</code> 等于 <span class="arithmatex">\(0\)</span> 时记录解。</li>
|
||||
</ul>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="2:12"><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" /><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">Zig</label></div>
|
||||
@@ -4326,7 +4326,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>如图 13-12 所示,为将数组 <span class="arithmatex">\([3, 4, 5]\)</span> 和目标元素 <span class="arithmatex">\(9\)</span> 输入到以上代码后的整体回溯过程。</p>
|
||||
<p>图 13-12 所示为将数组 <span class="arithmatex">\([3, 4, 5]\)</span> 和目标元素 <span class="arithmatex">\(9\)</span> 输入以上代码后的整体回溯过程。</p>
|
||||
<p><a class="glightbox" href="../subset_sum_problem.assets/subset_sum_i.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="子集和 I 回溯过程" class="animation-figure" src="../subset_sum_problem.assets/subset_sum_i.png" /></a></p>
|
||||
<p align="center"> 图 13-12 子集和 I 回溯过程 </p>
|
||||
|
||||
@@ -4341,8 +4341,8 @@
|
||||
<p align="center"> 图 13-13 相等元素导致的重复子集 </p>
|
||||
|
||||
<h3 id="1_1">1. 相等元素剪枝<a class="headerlink" href="#1_1" title="Permanent link">¶</a></h3>
|
||||
<p>为解决此问题,<strong>我们需要限制相等元素在每一轮中只被选择一次</strong>。实现方式比较巧妙:由于数组是已排序的,因此相等元素都是相邻的。这意味着在某轮选择中,若当前元素与其左边元素相等,则说明它已经被选择过,因此直接跳过当前元素。</p>
|
||||
<p>与此同时,<strong>本题规定数组中的每个元素只能被选择一次</strong>。幸运的是,我们也可以利用变量 <code>start</code> 来满足该约束:当做出选择 <span class="arithmatex">\(x_{i}\)</span> 后,设定下一轮从索引 <span class="arithmatex">\(i + 1\)</span> 开始向后遍历。这样即能去除重复子集,也能避免重复选择元素。</p>
|
||||
<p>为解决此问题,<strong>我们需要限制相等元素在每一轮中只能被选择一次</strong>。实现方式比较巧妙:由于数组是已排序的,因此相等元素都是相邻的。这意味着在某轮选择中,若当前元素与其左边元素相等,则说明它已经被选择过,因此直接跳过当前元素。</p>
|
||||
<p>与此同时,<strong>本题规定每个数组元素只能被选择一次</strong>。幸运的是,我们也可以利用变量 <code>start</code> 来满足该约束:当做出选择 <span class="arithmatex">\(x_{i}\)</span> 后,设定下一轮从索引 <span class="arithmatex">\(i + 1\)</span> 开始向后遍历。这样既能去除重复子集,也能避免重复选择元素。</p>
|
||||
<h3 id="2_1">2. 代码实现<a class="headerlink" href="#2_1" title="Permanent link">¶</a></h3>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="3:12"><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" /><input id="__tabbed_3_12" name="__tabbed_3" type="radio" /><div class="tabbed-labels"><label for="__tabbed_3_1">Python</label><label for="__tabbed_3_2">C++</label><label for="__tabbed_3_3">Java</label><label for="__tabbed_3_4">C#</label><label for="__tabbed_3_5">Go</label><label for="__tabbed_3_6">Swift</label><label for="__tabbed_3_7">JS</label><label for="__tabbed_3_8">TS</label><label for="__tabbed_3_9">Dart</label><label for="__tabbed_3_10">Rust</label><label for="__tabbed_3_11">C</label><label for="__tabbed_3_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
|
||||
@@ -3387,13 +3387,13 @@
|
||||
<li>回溯算法本质是穷举法,通过对解空间进行深度优先遍历来寻找符合条件的解。在搜索过程中,遇到满足条件的解则记录,直至找到所有解或遍历完成后结束。</li>
|
||||
<li>回溯算法的搜索过程包括尝试与回退两个部分。它通过深度优先搜索来尝试各种选择,当遇到不满足约束条件的情况时,则撤销上一步的选择,退回到之前的状态,并继续尝试其他选择。尝试与回退是两个方向相反的操作。</li>
|
||||
<li>回溯问题通常包含多个约束条件,它们可用于实现剪枝操作。剪枝可以提前结束不必要的搜索分支,大幅提升搜索效率。</li>
|
||||
<li>回溯算法主要可用于解决搜索问题和约束满足问题。组合优化问题虽然可以用回溯算法解决,但往往存在更高效率或更好效果的解法。</li>
|
||||
<li>全排列问题旨在搜索给定集合的所有可能的排列。我们借助一个数组来记录每个元素是否被选择,剪枝掉重复选择同一元素的搜索分支,确保每个元素只被选择一次。</li>
|
||||
<li>回溯算法主要可用于解决搜索问题和约束满足问题。组合优化问题虽然可以用回溯算法解决,但往往存在效率更高或效果更好的解法。</li>
|
||||
<li>全排列问题旨在搜索给定集合元素的所有可能的排列。我们借助一个数组来记录每个元素是否被选择,剪掉重复选择同一元素的搜索分支,确保每个元素只被选择一次。</li>
|
||||
<li>在全排列问题中,如果集合中存在重复元素,则最终结果会出现重复排列。我们需要约束相等元素在每轮中只能被选择一次,这通常借助一个哈希表来实现。</li>
|
||||
<li>子集和问题的目标是在给定集合中找到和为目标值的所有子集。集合不区分元素顺序,而搜索过程会输出所有顺序的结果,产生重复子集。我们在回溯前将数据进行排序,并设置一个变量来指示每一轮的遍历起点,从而将生成重复子集的搜索分支进行剪枝。</li>
|
||||
<li>子集和问题的目标是在给定集合中找到和为目标值的所有子集。集合不区分元素顺序,而搜索过程会输出所有顺序的结果,产生重复子集。我们在回溯前将数据进行排序,并设置一个变量来指示每一轮的遍历起始点,从而将生成重复子集的搜索分支进行剪枝。</li>
|
||||
<li>对于子集和问题,数组中的相等元素会产生重复集合。我们利用数组已排序的前置条件,通过判断相邻元素是否相等实现剪枝,从而确保相等元素在每轮中只能被选中一次。</li>
|
||||
<li><span class="arithmatex">\(n\)</span> 皇后旨在寻找将 <span class="arithmatex">\(n\)</span> 个皇后放置到 <span class="arithmatex">\(n \times n\)</span> 尺寸棋盘上的方案,要求所有皇后两两之间无法攻击对方。该问题的约束条件有行约束、列约束、主对角线和副对角线约束。为满足行约束,我们采用按行放置的策略,保证每一行放置一个皇后。</li>
|
||||
<li>列约束和对角线约束的处理方式类似。对于列约束,我们利用一个数组来记录每一列是否有皇后,从而指示选中的格子是否合法。对于对角线约束,我们借助两个数组来分别记录该主、副对角线是否存在皇后;难点在于找处在到同一主(副)对角线上格子满足的行列索引规律。</li>
|
||||
<li><span class="arithmatex">\(n\)</span> 皇后问题旨在寻找将 <span class="arithmatex">\(n\)</span> 个皇后放置到 <span class="arithmatex">\(n \times n\)</span> 尺寸棋盘上的方案,要求所有皇后两两之间无法攻击对方。该问题的约束条件有行约束、列约束、主对角线和副对角线约束。为满足行约束,我们采用按行放置的策略,保证每一行放置一个皇后。</li>
|
||||
<li>列约束和对角线约束的处理方式类似。对于列约束,我们利用一个数组来记录每一列是否有皇后,从而指示选中的格子是否合法。对于对角线约束,我们借助两个数组来分别记录该主、副对角线上是否存在皇后;难点在于找处在到同一主(副)对角线上格子满足的行列索引规律。</li>
|
||||
</ul>
|
||||
<h3 id="2-q-a">2. Q & A<a class="headerlink" href="#2-q-a" title="Permanent link">¶</a></h3>
|
||||
<div class="admonition question">
|
||||
|
||||
Reference in New Issue
Block a user