mirror of
https://github.com/krahets/hello-algo.git
synced 2025-02-03 07:01:55 +08:00
deploy
This commit is contained in:
parent
9a09f9407e
commit
3f666fa676
@ -3380,7 +3380,7 @@
|
||||
<li>修改 Markdown 源文件内容,检查内容的正确性,并尽量保持排版格式的统一。</li>
|
||||
<li>在页面底部填写修改说明,然后点击“Propose file change”按钮。页面跳转后,点击“Create pull request”按钮即可发起拉取请求。</li>
|
||||
</ol>
|
||||
<p><a class="glightbox" href="../contribution.assets/edit_markdown.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="页面编辑按键" src="../contribution.assets/edit_markdown.png" /></a></p>
|
||||
<p><a class="glightbox" href="../contribution.assets/edit_markdown.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="页面编辑按键" class="animation-figure" src="../contribution.assets/edit_markdown.png" /></a></p>
|
||||
<p align="center"> 图 16-1 页面编辑按键 </p>
|
||||
|
||||
<p>图片无法直接修改,需要通过新建 <a href="https://github.com/krahets/hello-algo/issues">Issue</a> 或评论留言来描述问题,我们会尽快重新绘制并替换图片。</p>
|
||||
|
@ -3292,7 +3292,7 @@
|
||||
<!-- Page content -->
|
||||
<h1 id="16">第 16 章 附录<a class="headerlink" href="#16" title="Permanent link">¶</a></h1>
|
||||
<div class="center-table">
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_appendix.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="附录" src="../assets/covers/chapter_appendix.jpg" width="600" /></a></p>
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_appendix.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="附录" class="cover-image" src="../assets/covers/chapter_appendix.jpg" /></a></p>
|
||||
</div>
|
||||
<h2 id="_1">本章内容<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
|
||||
<ul>
|
||||
|
@ -3477,7 +3477,7 @@
|
||||
<!-- Page content -->
|
||||
<h1 id="41">4.1 数组<a class="headerlink" href="#41" title="Permanent link">¶</a></h1>
|
||||
<p>「数组 array」是一种线性数据结构,其将相同类型元素存储在连续的内存空间中。我们将元素在数组中的位置称为该元素的「索引 index」。图 4-1 展示了数组的主要术语和概念。</p>
|
||||
<p><a class="glightbox" href="../array.assets/array_definition.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="数组定义与存储方式" src="../array.assets/array_definition.png" /></a></p>
|
||||
<p><a class="glightbox" href="../array.assets/array_definition.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="数组定义与存储方式" class="animation-figure" src="../array.assets/array_definition.png" /></a></p>
|
||||
<p align="center"> 图 4-1 数组定义与存储方式 </p>
|
||||
|
||||
<h2 id="411">4.1.1 数组常用操作<a class="headerlink" href="#411" title="Permanent link">¶</a></h2>
|
||||
@ -3568,7 +3568,7 @@
|
||||
</div>
|
||||
<h3 id="2">2. 访问元素<a class="headerlink" href="#2" title="Permanent link">¶</a></h3>
|
||||
<p>数组元素被存储在连续的内存空间中,这意味着计算数组元素的内存地址非常容易。给定数组内存地址(即首元素内存地址)和某个元素的索引,我们可以使用图 4-2 所示的公式计算得到该元素的内存地址,从而直接访问此元素。</p>
|
||||
<p><a class="glightbox" href="../array.assets/array_memory_location_calculation.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="数组元素的内存地址计算" src="../array.assets/array_memory_location_calculation.png" /></a></p>
|
||||
<p><a class="glightbox" href="../array.assets/array_memory_location_calculation.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="数组元素的内存地址计算" class="animation-figure" src="../array.assets/array_memory_location_calculation.png" /></a></p>
|
||||
<p align="center"> 图 4-2 数组元素的内存地址计算 </p>
|
||||
|
||||
<p>观察图 4-2 ,我们发现数组首个元素的索引为 <span class="arithmatex">\(0\)</span> ,这似乎有些反直觉,因为从 <span class="arithmatex">\(1\)</span> 开始计数会更自然。但从地址计算公式的角度看,<strong>索引的含义本质上是内存地址的偏移量</strong>。首个元素的地址偏移量是 <span class="arithmatex">\(0\)</span> ,因此它的索引为 <span class="arithmatex">\(0\)</span> 也是合理的。</p>
|
||||
@ -3711,7 +3711,7 @@
|
||||
</div>
|
||||
<h3 id="3">3. 插入元素<a class="headerlink" href="#3" title="Permanent link">¶</a></h3>
|
||||
<p>数组元素在内存中是“紧挨着的”,它们之间没有空间再存放任何数据。如图 4-3 所示,如果想要在数组中间插入一个元素,则需要将该元素之后的所有元素都向后移动一位,之后再把元素赋值给该索引。</p>
|
||||
<p><a class="glightbox" href="../array.assets/array_insert_element.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="数组插入元素示例" src="../array.assets/array_insert_element.png" /></a></p>
|
||||
<p><a class="glightbox" href="../array.assets/array_insert_element.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="数组插入元素示例" class="animation-figure" src="../array.assets/array_insert_element.png" /></a></p>
|
||||
<p align="center"> 图 4-3 数组插入元素示例 </p>
|
||||
|
||||
<p>值得注意的是,由于数组的长度是固定的,因此插入一个元素必定会导致数组尾部元素的“丢失”。我们将这个问题的解决方案留在列表章节中讨论。</p>
|
||||
@ -3864,7 +3864,7 @@
|
||||
</div>
|
||||
<h3 id="4">4. 删除元素<a class="headerlink" href="#4" title="Permanent link">¶</a></h3>
|
||||
<p>同理,如图 4-4 所示,若想要删除索引 <span class="arithmatex">\(i\)</span> 处的元素,则需要把索引 <span class="arithmatex">\(i\)</span> 之后的元素都向前移动一位。</p>
|
||||
<p><a class="glightbox" href="../array.assets/array_remove_element.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="数组删除元素示例" src="../array.assets/array_remove_element.png" /></a></p>
|
||||
<p><a class="glightbox" href="../array.assets/array_remove_element.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="数组删除元素示例" class="animation-figure" src="../array.assets/array_remove_element.png" /></a></p>
|
||||
<p align="center"> 图 4-4 数组删除元素示例 </p>
|
||||
|
||||
<p>请注意,删除元素完成后,原先末尾的元素变得“无意义”了,所以我们无须特意去修改它。</p>
|
||||
|
@ -3291,9 +3291,7 @@
|
||||
|
||||
<!-- Page content -->
|
||||
<h1 id="4">第 4 章 数组与链表<a class="headerlink" href="#4" title="Permanent link">¶</a></h1>
|
||||
<div class="center-table">
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_array_and_linkedlist.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="数组与链表" src="../assets/covers/chapter_array_and_linkedlist.jpg" width="600" /></a></p>
|
||||
</div>
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_array_and_linkedlist.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="数组与链表" class="cover-image" src="../assets/covers/chapter_array_and_linkedlist.jpg" /></a></p>
|
||||
<div class="admonition abstract">
|
||||
<p class="admonition-title">Abstract</p>
|
||||
<p>数据结构的世界如同一堵厚实的砖墙。</p>
|
||||
|
@ -3465,7 +3465,7 @@
|
||||
<p>内存空间是所有程序的公共资源,在一个复杂的系统运行环境下,空闲的内存空间可能散落在内存各处。我们知道,存储数组的内存空间必须是连续的,而当数组非常大时,内存可能无法提供如此大的连续空间。此时链表的灵活性优势就体现出来了。</p>
|
||||
<p>「链表 linked list」是一种线性数据结构,其中的每个元素都是一个节点对象,各个节点通过“引用”相连接。引用记录了下一个节点的内存地址,通过它可以从当前节点访问到下一个节点。</p>
|
||||
<p>链表的设计使得各个节点可以被分散存储在内存各处,它们的内存地址是无须连续的。</p>
|
||||
<p><a class="glightbox" href="../linked_list.assets/linkedlist_definition.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="链表定义与存储方式" src="../linked_list.assets/linkedlist_definition.png" /></a></p>
|
||||
<p><a class="glightbox" href="../linked_list.assets/linkedlist_definition.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="链表定义与存储方式" class="animation-figure" src="../linked_list.assets/linkedlist_definition.png" /></a></p>
|
||||
<p align="center"> 图 4-5 链表定义与存储方式 </p>
|
||||
|
||||
<p>观察图 4-5 ,链表的组成单位是「节点 node」对象。每个节点都包含两项数据:节点的“值”和指向下一节点的“引用”。</p>
|
||||
@ -3811,7 +3811,7 @@
|
||||
<h3 id="2">2. 插入节点<a class="headerlink" href="#2" title="Permanent link">¶</a></h3>
|
||||
<p>在链表中插入节点非常容易。如图 4-6 所示,假设我们想在相邻的两个节点 <code>n0</code> 和 <code>n1</code> 之间插入一个新节点 <code>P</code> ,<strong>则只需要改变两个节点引用(指针)即可</strong>,时间复杂度为 <span class="arithmatex">\(O(1)\)</span> 。</p>
|
||||
<p>相比之下,在数组中插入元素的时间复杂度为 <span class="arithmatex">\(O(n)\)</span> ,在大数据量下的效率较低。</p>
|
||||
<p><a class="glightbox" href="../linked_list.assets/linkedlist_insert_node.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="链表插入节点示例" src="../linked_list.assets/linkedlist_insert_node.png" /></a></p>
|
||||
<p><a class="glightbox" href="../linked_list.assets/linkedlist_insert_node.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="链表插入节点示例" class="animation-figure" src="../linked_list.assets/linkedlist_insert_node.png" /></a></p>
|
||||
<p align="center"> 图 4-6 链表插入节点示例 </p>
|
||||
|
||||
<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>
|
||||
@ -3929,7 +3929,7 @@
|
||||
<h3 id="3">3. 删除节点<a class="headerlink" href="#3" title="Permanent link">¶</a></h3>
|
||||
<p>如图 4-7 所示,在链表中删除节点也非常方便,<strong>只需改变一个节点的引用(指针)即可</strong>。</p>
|
||||
<p>请注意,尽管在删除操作完成后节点 <code>P</code> 仍然指向 <code>n1</code> ,但实际上遍历此链表已经无法访问到 <code>P</code> ,这意味着 <code>P</code> 已经不再属于该链表了。</p>
|
||||
<p><a class="glightbox" href="../linked_list.assets/linkedlist_remove_node.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="链表删除节点" src="../linked_list.assets/linkedlist_remove_node.png" /></a></p>
|
||||
<p><a class="glightbox" href="../linked_list.assets/linkedlist_remove_node.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="链表删除节点" class="animation-figure" src="../linked_list.assets/linkedlist_remove_node.png" /></a></p>
|
||||
<p align="center"> 图 4-7 链表删除节点 </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>
|
||||
@ -4644,7 +4644,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p><a class="glightbox" href="../linked_list.assets/linkedlist_common_types.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="常见链表种类" src="../linked_list.assets/linkedlist_common_types.png" /></a></p>
|
||||
<p><a class="glightbox" href="../linked_list.assets/linkedlist_common_types.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="常见链表种类" class="animation-figure" src="../linked_list.assets/linkedlist_common_types.png" /></a></p>
|
||||
<p align="center"> 图 4-8 常见链表种类 </p>
|
||||
|
||||
<h2 id="424">4.2.4 链表典型应用<a class="headerlink" href="#424" title="Permanent link">¶</a></h2>
|
||||
|
@ -3587,7 +3587,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_nodes.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="在前序遍历中搜索节点" src="../backtracking_algorithm.assets/preorder_find_nodes.png" /></a></p>
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_nodes.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="在前序遍历中搜索节点" class="animation-figure" src="../backtracking_algorithm.assets/preorder_find_nodes.png" /></a></p>
|
||||
<p align="center"> 图 13-1 在前序遍历中搜索节点 </p>
|
||||
|
||||
<h2 id="1311">13.1.1 尝试与回退<a class="headerlink" href="#1311" title="Permanent link">¶</a></h2>
|
||||
@ -3832,37 +3832,37 @@
|
||||
<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">
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_paths_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="尝试与回退" src="../backtracking_algorithm.assets/preorder_find_paths_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_paths_step1.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_paths_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_paths_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_find_paths_step2" src="../backtracking_algorithm.assets/preorder_find_paths_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_paths_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_find_paths_step2" class="animation-figure" src="../backtracking_algorithm.assets/preorder_find_paths_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_paths_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_find_paths_step3" src="../backtracking_algorithm.assets/preorder_find_paths_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_paths_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_find_paths_step3" class="animation-figure" src="../backtracking_algorithm.assets/preorder_find_paths_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_paths_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_find_paths_step4" src="../backtracking_algorithm.assets/preorder_find_paths_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_paths_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_find_paths_step4" class="animation-figure" src="../backtracking_algorithm.assets/preorder_find_paths_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_paths_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_find_paths_step5" src="../backtracking_algorithm.assets/preorder_find_paths_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_paths_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_find_paths_step5" class="animation-figure" src="../backtracking_algorithm.assets/preorder_find_paths_step5.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_paths_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_find_paths_step6" src="../backtracking_algorithm.assets/preorder_find_paths_step6.png" /></a></p>
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_paths_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_find_paths_step6" class="animation-figure" src="../backtracking_algorithm.assets/preorder_find_paths_step6.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_paths_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_find_paths_step7" src="../backtracking_algorithm.assets/preorder_find_paths_step7.png" /></a></p>
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_paths_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_find_paths_step7" class="animation-figure" src="../backtracking_algorithm.assets/preorder_find_paths_step7.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_paths_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_find_paths_step8" src="../backtracking_algorithm.assets/preorder_find_paths_step8.png" /></a></p>
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_paths_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_find_paths_step8" class="animation-figure" src="../backtracking_algorithm.assets/preorder_find_paths_step8.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_paths_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_find_paths_step9" src="../backtracking_algorithm.assets/preorder_find_paths_step9.png" /></a></p>
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_paths_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_find_paths_step9" class="animation-figure" src="../backtracking_algorithm.assets/preorder_find_paths_step9.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_paths_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_find_paths_step10" src="../backtracking_algorithm.assets/preorder_find_paths_step10.png" /></a></p>
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_paths_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_find_paths_step10" class="animation-figure" src="../backtracking_algorithm.assets/preorder_find_paths_step10.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_paths_step11.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_find_paths_step11" src="../backtracking_algorithm.assets/preorder_find_paths_step11.png" /></a></p>
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/preorder_find_paths_step11.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_find_paths_step11" class="animation-figure" src="../backtracking_algorithm.assets/preorder_find_paths_step11.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -4114,7 +4114,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<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="根据约束条件剪枝" src="../backtracking_algorithm.assets/preorder_find_constrained_paths.png" /></a></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>
|
||||
@ -4944,7 +4944,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<p>根据题意,我们在找到值为 <span class="arithmatex">\(7\)</span> 的节点后应该继续搜索,<strong>因此需要将记录解之后的 <code>return</code> 语句删除</strong>。图 13-4 对比了保留或删除 <code>return</code> 语句的搜索过程。</p>
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/backtrack_remove_return_or_not.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="保留与删除 return 的搜索过程对比" src="../backtracking_algorithm.assets/backtrack_remove_return_or_not.png" /></a></p>
|
||||
<p><a class="glightbox" href="../backtracking_algorithm.assets/backtrack_remove_return_or_not.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="保留与删除 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>
|
||||
|
@ -3292,7 +3292,7 @@
|
||||
<!-- Page content -->
|
||||
<h1 id="13">第 13 章 回溯<a class="headerlink" href="#13" title="Permanent link">¶</a></h1>
|
||||
<div class="center-table">
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_backtracking.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="回溯" src="../assets/covers/chapter_backtracking.jpg" width="600" /></a></p>
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_backtracking.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="回溯" class="cover-image" src="../assets/covers/chapter_backtracking.jpg" /></a></p>
|
||||
</div>
|
||||
<div class="admonition abstract">
|
||||
<p class="admonition-title">Abstract</p>
|
||||
|
@ -3371,18 +3371,18 @@
|
||||
<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 皇后问题的解" src="../n_queens_problem.assets/solution_4_queens.png" /></a></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>
|
||||
<p align="center"> 图 13-15 4 皇后问题的解 </p>
|
||||
|
||||
<p>图 13-16 展示了本题的三个约束条件:<strong>多个皇后不能在同一行、同一列、同一对角线</strong>。值得注意的是,对角线分为主对角线 <code>\</code> 和次对角线 <code>/</code> 两种。</p>
|
||||
<p><a class="glightbox" href="../n_queens_problem.assets/n_queens_constraints.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="n 皇后问题的约束条件" src="../n_queens_problem.assets/n_queens_constraints.png" /></a></p>
|
||||
<p><a class="glightbox" href="../n_queens_problem.assets/n_queens_constraints.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="n 皇后问题的约束条件" class="animation-figure" src="../n_queens_problem.assets/n_queens_constraints.png" /></a></p>
|
||||
<p align="center"> 图 13-16 n 皇后问题的约束条件 </p>
|
||||
|
||||
<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><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="逐行放置策略" src="../n_queens_problem.assets/n_queens_placing.png" /></a></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>
|
||||
@ -3391,7 +3391,7 @@
|
||||
<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>同理,<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="处理列约束和对角线约束" src="../n_queens_problem.assets/n_queens_cols_diagonals.png" /></a></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>
|
||||
|
||||
<h3 id="3">3. 代码实现<a class="headerlink" href="#3" title="Permanent link">¶</a></h3>
|
||||
|
@ -3482,7 +3482,7 @@
|
||||
<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><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="全排列的递归树" src="../permutations_problem.assets/permutations_i.png" /></a></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>
|
||||
|
||||
<h3 id="1">1. 重复选择剪枝<a class="headerlink" href="#1" title="Permanent link">¶</a></h3>
|
||||
@ -3492,7 +3492,7 @@
|
||||
<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="全排列剪枝示例" src="../permutations_problem.assets/permutations_i_pruning.png" /></a></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>
|
||||
@ -3901,7 +3901,7 @@
|
||||
</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><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="重复排列" src="../permutations_problem.assets/permutations_ii.png" /></a></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>
|
||||
@ -3909,7 +3909,7 @@
|
||||
<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><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="重复排列剪枝" src="../permutations_problem.assets/permutations_ii_pruning.png" /></a></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>
|
||||
@ -4342,7 +4342,7 @@
|
||||
<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="两种剪枝条件的作用范围" src="../permutations_problem.assets/permutations_ii_pruning_summary.png" /></a></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>
|
||||
<p align="center"> 图 13-9 两种剪枝条件的作用范围 </p>
|
||||
|
||||
<!-- Source file information -->
|
||||
|
@ -3848,7 +3848,7 @@
|
||||
</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><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="子集搜索与越界剪枝" src="../subset_sum_problem.assets/subset_sum_i_naive.png" /></a></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>
|
||||
|
||||
<p>为了去除重复子集,<strong>一种直接的思路是对结果列表进行去重</strong>。但这个方法效率很低,有两方面原因。</p>
|
||||
@ -3868,7 +3868,7 @@
|
||||
<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>
|
||||
</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="不同选择顺序导致的重复子集" src="../subset_sum_problem.assets/subset_sum_i_pruning.png" /></a></p>
|
||||
<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>
|
||||
@ -4297,7 +4297,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<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 回溯过程" src="../subset_sum_problem.assets/subset_sum_i.png" /></a></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>
|
||||
|
||||
<h2 id="1332">13.3.2 考虑重复元素的情况<a class="headerlink" href="#1332" title="Permanent link">¶</a></h2>
|
||||
@ -4307,7 +4307,7 @@
|
||||
</div>
|
||||
<p>相比于上题,<strong>本题的输入数组可能包含重复元素</strong>,这引入了新的问题。例如,给定数组 <span class="arithmatex">\([4, \hat{4}, 5]\)</span> 和目标元素 <span class="arithmatex">\(9\)</span> ,则现有代码的输出结果为 <span class="arithmatex">\([4, 5], [\hat{4}, 5]\)</span> ,出现了重复子集。</p>
|
||||
<p><strong>造成这种重复的原因是相等元素在某轮中被多次选择</strong>。在图 13-13 中,第一轮共有三个选择,其中两个都为 <span class="arithmatex">\(4\)</span> ,会产生两个重复的搜索分支,从而输出重复子集;同理,第二轮的两个 <span class="arithmatex">\(4\)</span> 也会产生重复子集。</p>
|
||||
<p><a class="glightbox" href="../subset_sum_problem.assets/subset_sum_ii_repeat.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="相等元素导致的重复子集" src="../subset_sum_problem.assets/subset_sum_ii_repeat.png" /></a></p>
|
||||
<p><a class="glightbox" href="../subset_sum_problem.assets/subset_sum_ii_repeat.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_ii_repeat.png" /></a></p>
|
||||
<p align="center"> 图 13-13 相等元素导致的重复子集 </p>
|
||||
|
||||
<h3 id="1_1">1. 相等元素剪枝<a class="headerlink" href="#1_1" title="Permanent link">¶</a></h3>
|
||||
@ -4786,7 +4786,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<p>图 13-14 展示了数组 <span class="arithmatex">\([4, 4, 5]\)</span> 和目标元素 <span class="arithmatex">\(9\)</span> 的回溯过程,共包含四种剪枝操作。请你将图示与代码注释相结合,理解整个搜索过程,以及每种剪枝操作是如何工作的。</p>
|
||||
<p><a class="glightbox" href="../subset_sum_problem.assets/subset_sum_ii.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="子集和 II 回溯过程" src="../subset_sum_problem.assets/subset_sum_ii.png" /></a></p>
|
||||
<p><a class="glightbox" href="../subset_sum_problem.assets/subset_sum_ii.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="子集和 II 回溯过程" class="animation-figure" src="../subset_sum_problem.assets/subset_sum_ii.png" /></a></p>
|
||||
<p align="center"> 图 13-14 子集和 II 回溯过程 </p>
|
||||
|
||||
<!-- Source file information -->
|
||||
|
@ -3292,7 +3292,7 @@
|
||||
<!-- Page content -->
|
||||
<h1 id="2">第 2 章 复杂度分析<a class="headerlink" href="#2" title="Permanent link">¶</a></h1>
|
||||
<div class="center-table">
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_complexity_analysis.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="复杂度分析" src="../assets/covers/chapter_complexity_analysis.jpg" width="600" /></a></p>
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_complexity_analysis.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="复杂度分析" class="cover-image" src="../assets/covers/chapter_complexity_analysis.jpg" /></a></p>
|
||||
</div>
|
||||
<div class="admonition abstract">
|
||||
<p class="admonition-title">Abstract</p>
|
||||
|
@ -3627,7 +3627,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<p>图 2-1 展示了该求和函数的流程框图。</p>
|
||||
<p><a class="glightbox" href="../iteration_and_recursion.assets/iteration.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="求和函数的流程框图" src="../iteration_and_recursion.assets/iteration.png" /></a></p>
|
||||
<p><a class="glightbox" href="../iteration_and_recursion.assets/iteration.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="求和函数的流程框图" class="animation-figure" src="../iteration_and_recursion.assets/iteration.png" /></a></p>
|
||||
<p align="center"> 图 2-1 求和函数的流程框图 </p>
|
||||
|
||||
<p>此求和函数的操作数量与输入数据大小 <span class="arithmatex">\(n\)</span> 成正比,或者说成“线性关系”。实际上,<strong>时间复杂度描述的就是这个“线性关系”</strong>。相关内容将会在下一节中详细介绍。</p>
|
||||
@ -4195,7 +4195,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<p>图 2-2 给出了该嵌套循环的流程框图。</p>
|
||||
<p><a class="glightbox" href="../iteration_and_recursion.assets/nested_iteration.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="嵌套循环的流程框图" src="../iteration_and_recursion.assets/nested_iteration.png" /></a></p>
|
||||
<p><a class="glightbox" href="../iteration_and_recursion.assets/nested_iteration.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="嵌套循环的流程框图" class="animation-figure" src="../iteration_and_recursion.assets/nested_iteration.png" /></a></p>
|
||||
<p align="center"> 图 2-2 嵌套循环的流程框图 </p>
|
||||
|
||||
<p>在这种情况下,函数的操作数量与 <span class="arithmatex">\(n^2\)</span> 成正比,或者说算法运行时间和输入数据大小 <span class="arithmatex">\(n\)</span> 成“平方关系”。</p>
|
||||
@ -4374,7 +4374,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<p>图 2-3 展示了该函数的递归过程。</p>
|
||||
<p><a class="glightbox" href="../iteration_and_recursion.assets/recursion_sum.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="求和函数的递归过程" src="../iteration_and_recursion.assets/recursion_sum.png" /></a></p>
|
||||
<p><a class="glightbox" href="../iteration_and_recursion.assets/recursion_sum.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="求和函数的递归过程" class="animation-figure" src="../iteration_and_recursion.assets/recursion_sum.png" /></a></p>
|
||||
<p align="center"> 图 2-3 求和函数的递归过程 </p>
|
||||
|
||||
<p>虽然从计算角度看,迭代与递归可以得到相同的结果,<strong>但它们代表了两种完全不同的思考和解决问题的范式</strong>。</p>
|
||||
@ -4394,7 +4394,7 @@
|
||||
<li>递归调用函数会产生额外的开销。<strong>因此递归通常比循环的时间效率更低</strong>。</li>
|
||||
</ul>
|
||||
<p>如图 2-4 所示,在触发终止条件前,同时存在 <span class="arithmatex">\(n\)</span> 个未返回的递归函数,<strong>递归深度为 <span class="arithmatex">\(n\)</span></strong> 。</p>
|
||||
<p><a class="glightbox" href="../iteration_and_recursion.assets/recursion_sum_depth.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="递归调用深度" src="../iteration_and_recursion.assets/recursion_sum_depth.png" /></a></p>
|
||||
<p><a class="glightbox" href="../iteration_and_recursion.assets/recursion_sum_depth.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="递归调用深度" class="animation-figure" src="../iteration_and_recursion.assets/recursion_sum_depth.png" /></a></p>
|
||||
<p align="center"> 图 2-4 递归调用深度 </p>
|
||||
|
||||
<p>在实际中,编程语言允许的递归深度通常是有限的,过深的递归可能导致栈溢出报错。</p>
|
||||
@ -4546,7 +4546,7 @@
|
||||
<li><strong>普通递归</strong>:求和操作是在“归”的过程中执行的,每层返回后都要再执行一次求和操作。</li>
|
||||
<li><strong>尾递归</strong>:求和操作是在“递”的过程中执行的,“归”的过程只需层层返回。</li>
|
||||
</ul>
|
||||
<p><a class="glightbox" href="../iteration_and_recursion.assets/tail_recursion_sum.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="尾递归过程" src="../iteration_and_recursion.assets/tail_recursion_sum.png" /></a></p>
|
||||
<p><a class="glightbox" href="../iteration_and_recursion.assets/tail_recursion_sum.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="尾递归过程" class="animation-figure" src="../iteration_and_recursion.assets/tail_recursion_sum.png" /></a></p>
|
||||
<p align="center"> 图 2-5 尾递归过程 </p>
|
||||
|
||||
<div class="admonition tip">
|
||||
@ -4726,7 +4726,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<p>观察以上代码,我们在函数内递归调用了两个函数,<strong>这意味着从一个调用产生了两个调用分支</strong>。如图 2-6 所示,这样不断递归调用下去,最终将产生一个层数为 <span class="arithmatex">\(n\)</span> 的「递归树 recursion tree」。</p>
|
||||
<p><a class="glightbox" href="../iteration_and_recursion.assets/recursion_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="斐波那契数列的递归树" src="../iteration_and_recursion.assets/recursion_tree.png" /></a></p>
|
||||
<p><a class="glightbox" href="../iteration_and_recursion.assets/recursion_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="斐波那契数列的递归树" class="animation-figure" src="../iteration_and_recursion.assets/recursion_tree.png" /></a></p>
|
||||
<p align="center"> 图 2-6 斐波那契数列的递归树 </p>
|
||||
|
||||
<p>本质上看,递归体现“将问题分解为更小子问题”的思维范式,这种分治策略是至关重要的。</p>
|
||||
|
@ -3478,7 +3478,7 @@
|
||||
<li><strong>指令空间</strong>:用于保存编译后的程序指令,在实际统计中通常忽略不计。</li>
|
||||
</ul>
|
||||
<p>在分析一段程序的空间复杂度时,<strong>我们通常统计暂存数据、栈帧空间和输出数据三部分</strong>。</p>
|
||||
<p><a class="glightbox" href="../space_complexity.assets/space_types.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="算法使用的相关空间" src="../space_complexity.assets/space_types.png" /></a></p>
|
||||
<p><a class="glightbox" href="../space_complexity.assets/space_types.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="算法使用的相关空间" class="animation-figure" src="../space_complexity.assets/space_types.png" /></a></p>
|
||||
<p align="center"> 图 2-15 算法使用的相关空间 </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>
|
||||
@ -4104,7 +4104,7 @@ O(1) < O(\log n) < O(n) < O(n^2) < O(2^n) \newline
|
||||
\text{常数阶} < \text{对数阶} < \text{线性阶} < \text{平方阶} < \text{指数阶}
|
||||
\end{aligned}
|
||||
\]</div>
|
||||
<p><a class="glightbox" href="../space_complexity.assets/space_complexity_common_types.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="常见的空间复杂度类型" src="../space_complexity.assets/space_complexity_common_types.png" /></a></p>
|
||||
<p><a class="glightbox" href="../space_complexity.assets/space_complexity_common_types.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="常见的空间复杂度类型" class="animation-figure" src="../space_complexity.assets/space_complexity_common_types.png" /></a></p>
|
||||
<p align="center"> 图 2-16 常见的空间复杂度类型 </p>
|
||||
|
||||
<h3 id="1-o1">1. 常数阶 <span class="arithmatex">\(O(1)\)</span><a class="headerlink" href="#1-o1" title="Permanent link">¶</a></h3>
|
||||
@ -4783,7 +4783,7 @@ O(1) < O(\log n) < O(n) < O(n^2) < O(2^n) \newline
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p><a class="glightbox" href="../space_complexity.assets/space_complexity_recursive_linear.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="递归函数产生的线性阶空间复杂度" src="../space_complexity.assets/space_complexity_recursive_linear.png" /></a></p>
|
||||
<p><a class="glightbox" href="../space_complexity.assets/space_complexity_recursive_linear.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="递归函数产生的线性阶空间复杂度" class="animation-figure" src="../space_complexity.assets/space_complexity_recursive_linear.png" /></a></p>
|
||||
<p align="center"> 图 2-17 递归函数产生的线性阶空间复杂度 </p>
|
||||
|
||||
<h3 id="3-on2">3. 平方阶 <span class="arithmatex">\(O(n^2)\)</span><a class="headerlink" href="#3-on2" title="Permanent link">¶</a></h3>
|
||||
@ -5118,7 +5118,7 @@ O(1) < O(\log n) < O(n) < O(n^2) < O(2^n) \newline
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p><a class="glightbox" href="../space_complexity.assets/space_complexity_recursive_quadratic.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="递归函数产生的平方阶空间复杂度" src="../space_complexity.assets/space_complexity_recursive_quadratic.png" /></a></p>
|
||||
<p><a class="glightbox" href="../space_complexity.assets/space_complexity_recursive_quadratic.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="递归函数产生的平方阶空间复杂度" class="animation-figure" src="../space_complexity.assets/space_complexity_recursive_quadratic.png" /></a></p>
|
||||
<p align="center"> 图 2-18 递归函数产生的平方阶空间复杂度 </p>
|
||||
|
||||
<h3 id="4-o2n">4. 指数阶 <span class="arithmatex">\(O(2^n)\)</span><a class="headerlink" href="#4-o2n" title="Permanent link">¶</a></h3>
|
||||
@ -5268,7 +5268,7 @@ O(1) < O(\log n) < O(n) < O(n^2) < O(2^n) \newline
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p><a class="glightbox" href="../space_complexity.assets/space_complexity_exponential.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="满二叉树产生的指数阶空间复杂度" src="../space_complexity.assets/space_complexity_exponential.png" /></a></p>
|
||||
<p><a class="glightbox" href="../space_complexity.assets/space_complexity_exponential.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="满二叉树产生的指数阶空间复杂度" class="animation-figure" src="../space_complexity.assets/space_complexity_exponential.png" /></a></p>
|
||||
<p align="center"> 图 2-19 满二叉树产生的指数阶空间复杂度 </p>
|
||||
|
||||
<h3 id="5-olog-n">5. 对数阶 <span class="arithmatex">\(O(\log n)\)</span><a class="headerlink" href="#5-olog-n" title="Permanent link">¶</a></h3>
|
||||
|
@ -3954,7 +3954,7 @@
|
||||
<li>算法 <code>B</code> 中的打印操作需要循环 <span class="arithmatex">\(n\)</span> 次,算法运行时间随着 <span class="arithmatex">\(n\)</span> 增大呈线性增长。此算法的时间复杂度被称为“线性阶”。</li>
|
||||
<li>算法 <code>C</code> 中的打印操作需要循环 <span class="arithmatex">\(1000000\)</span> 次,虽然运行时间很长,但它与输入数据大小 <span class="arithmatex">\(n\)</span> 无关。因此 <code>C</code> 的时间复杂度和 <code>A</code> 相同,仍为“常数阶”。</li>
|
||||
</ul>
|
||||
<p><a class="glightbox" href="../time_complexity.assets/time_complexity_simple_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="算法 A、B 和 C 的时间增长趋势" src="../time_complexity.assets/time_complexity_simple_example.png" /></a></p>
|
||||
<p><a class="glightbox" href="../time_complexity.assets/time_complexity_simple_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="算法 A、B 和 C 的时间增长趋势" class="animation-figure" src="../time_complexity.assets/time_complexity_simple_example.png" /></a></p>
|
||||
<p align="center"> 图 2-7 算法 A、B 和 C 的时间增长趋势 </p>
|
||||
|
||||
<p>相较于直接统计算法运行时间,时间复杂度分析有哪些特点呢?</p>
|
||||
@ -4124,7 +4124,7 @@ T(n) = 3 + 2n
|
||||
<p>若存在正实数 <span class="arithmatex">\(c\)</span> 和实数 <span class="arithmatex">\(n_0\)</span> ,使得对于所有的 <span class="arithmatex">\(n > n_0\)</span> ,均有 <span class="arithmatex">\(T(n) \leq c \cdot f(n)\)</span> ,则可认为 <span class="arithmatex">\(f(n)\)</span> 给出了 <span class="arithmatex">\(T(n)\)</span> 的一个渐近上界,记为 <span class="arithmatex">\(T(n) = O(f(n))\)</span> 。</p>
|
||||
</div>
|
||||
<p>如图 2-8 所示,计算渐近上界就是寻找一个函数 <span class="arithmatex">\(f(n)\)</span> ,使得当 <span class="arithmatex">\(n\)</span> 趋向于无穷大时,<span class="arithmatex">\(T(n)\)</span> 和 <span class="arithmatex">\(f(n)\)</span> 处于相同的增长级别,仅相差一个常数项 <span class="arithmatex">\(c\)</span> 的倍数。</p>
|
||||
<p><a class="glightbox" href="../time_complexity.assets/asymptotic_upper_bound.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="函数的渐近上界" src="../time_complexity.assets/asymptotic_upper_bound.png" /></a></p>
|
||||
<p><a class="glightbox" href="../time_complexity.assets/asymptotic_upper_bound.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="函数的渐近上界" class="animation-figure" src="../time_complexity.assets/asymptotic_upper_bound.png" /></a></p>
|
||||
<p align="center"> 图 2-8 函数的渐近上界 </p>
|
||||
|
||||
<h2 id="233">2.3.3 推算方法<a class="headerlink" href="#233" title="Permanent link">¶</a></h2>
|
||||
@ -4399,7 +4399,7 @@ O(1) < O(\log n) < O(n) < O(n \log n) < O(n^2) < O(2^n) < O(n!
|
||||
\text{常数阶} < \text{对数阶} < \text{线性阶} < \text{线性对数阶} < \text{平方阶} < \text{指数阶} < \text{阶乘阶}
|
||||
\end{aligned}
|
||||
\]</div>
|
||||
<p><a class="glightbox" href="../time_complexity.assets/time_complexity_common_types.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="常见的时间复杂度类型" src="../time_complexity.assets/time_complexity_common_types.png" /></a></p>
|
||||
<p><a class="glightbox" href="../time_complexity.assets/time_complexity_common_types.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="常见的时间复杂度类型" class="animation-figure" src="../time_complexity.assets/time_complexity_common_types.png" /></a></p>
|
||||
<p align="center"> 图 2-9 常见的时间复杂度类型 </p>
|
||||
|
||||
<h3 id="1-o1">1. 常数阶 <span class="arithmatex">\(O(1)\)</span><a class="headerlink" href="#1-o1" title="Permanent link">¶</a></h3>
|
||||
@ -5000,7 +5000,7 @@ O(1) < O(\log n) < O(n) < O(n \log n) < O(n^2) < O(2^n) < O(n!
|
||||
</div>
|
||||
</div>
|
||||
<p>图 2-10 对比了常数阶、线性阶和平方阶三种时间复杂度。</p>
|
||||
<p><a class="glightbox" href="../time_complexity.assets/time_complexity_constant_linear_quadratic.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="常数阶、线性阶和平方阶的时间复杂度" src="../time_complexity.assets/time_complexity_constant_linear_quadratic.png" /></a></p>
|
||||
<p><a class="glightbox" href="../time_complexity.assets/time_complexity_constant_linear_quadratic.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="常数阶、线性阶和平方阶的时间复杂度" class="animation-figure" src="../time_complexity.assets/time_complexity_constant_linear_quadratic.png" /></a></p>
|
||||
<p align="center"> 图 2-10 常数阶、线性阶和平方阶的时间复杂度 </p>
|
||||
|
||||
<p>以冒泡排序为例,外层循环执行 <span class="arithmatex">\(n - 1\)</span> 次,内层循环执行 <span class="arithmatex">\(n-1\)</span>、<span class="arithmatex">\(n-2\)</span>、<span class="arithmatex">\(\dots\)</span>、<span class="arithmatex">\(2\)</span>、<span class="arithmatex">\(1\)</span> 次,平均为 <span class="arithmatex">\(n / 2\)</span> 次,因此时间复杂度为 <span class="arithmatex">\(O((n - 1) n / 2) = O(n^2)\)</span> 。</p>
|
||||
@ -5461,7 +5461,7 @@ O(1) < O(\log n) < O(n) < O(n \log n) < O(n^2) < O(2^n) < O(n!
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p><a class="glightbox" href="../time_complexity.assets/time_complexity_exponential.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="指数阶的时间复杂度" src="../time_complexity.assets/time_complexity_exponential.png" /></a></p>
|
||||
<p><a class="glightbox" href="../time_complexity.assets/time_complexity_exponential.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="指数阶的时间复杂度" class="animation-figure" src="../time_complexity.assets/time_complexity_exponential.png" /></a></p>
|
||||
<p align="center"> 图 2-11 指数阶的时间复杂度 </p>
|
||||
|
||||
<p>在实际算法中,指数阶常出现于递归函数中。例如在以下代码中,其递归地一分为二,经过 <span class="arithmatex">\(n\)</span> 次分裂后停止:</p>
|
||||
@ -5727,7 +5727,7 @@ O(1) < O(\log n) < O(n) < O(n \log n) < O(n^2) < O(2^n) < O(n!
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p><a class="glightbox" href="../time_complexity.assets/time_complexity_logarithmic.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="对数阶的时间复杂度" src="../time_complexity.assets/time_complexity_logarithmic.png" /></a></p>
|
||||
<p><a class="glightbox" href="../time_complexity.assets/time_complexity_logarithmic.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="对数阶的时间复杂度" class="animation-figure" src="../time_complexity.assets/time_complexity_logarithmic.png" /></a></p>
|
||||
<p align="center"> 图 2-12 对数阶的时间复杂度 </p>
|
||||
|
||||
<p>与指数阶类似,对数阶也常出现于递归函数中。以下代码形成了一个高度为 <span class="arithmatex">\(\log_2 n\)</span> 的递归树:</p>
|
||||
@ -6009,7 +6009,7 @@ O(\log_m n) = O(\log_k n / \log_k m) = O(\log_k n)
|
||||
</div>
|
||||
</div>
|
||||
<p>图 2-13 展示了线性对数阶的生成方式。二叉树的每一层的操作总数都为 <span class="arithmatex">\(n\)</span> ,树共有 <span class="arithmatex">\(\log_2 n + 1\)</span> 层,因此时间复杂度为 <span class="arithmatex">\(O(n \log n)\)</span> 。</p>
|
||||
<p><a class="glightbox" href="../time_complexity.assets/time_complexity_logarithmic_linear.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="线性对数阶的时间复杂度" src="../time_complexity.assets/time_complexity_logarithmic_linear.png" /></a></p>
|
||||
<p><a class="glightbox" href="../time_complexity.assets/time_complexity_logarithmic_linear.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="线性对数阶的时间复杂度" class="animation-figure" src="../time_complexity.assets/time_complexity_logarithmic_linear.png" /></a></p>
|
||||
<p align="center"> 图 2-13 线性对数阶的时间复杂度 </p>
|
||||
|
||||
<p>主流排序算法的时间复杂度通常为 <span class="arithmatex">\(O(n \log n)\)</span> ,例如快速排序、归并排序、堆排序等。</p>
|
||||
@ -6187,7 +6187,7 @@ n! = n \times (n - 1) \times (n - 2) \times \dots \times 2 \times 1
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p><a class="glightbox" href="../time_complexity.assets/time_complexity_factorial.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="阶乘阶的时间复杂度" src="../time_complexity.assets/time_complexity_factorial.png" /></a></p>
|
||||
<p><a class="glightbox" href="../time_complexity.assets/time_complexity_factorial.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="阶乘阶的时间复杂度" class="animation-figure" src="../time_complexity.assets/time_complexity_factorial.png" /></a></p>
|
||||
<p align="center"> 图 2-14 阶乘阶的时间复杂度 </p>
|
||||
|
||||
<p>请注意,因为当 <span class="arithmatex">\(n \geq 4\)</span> 时恒有 <span class="arithmatex">\(n! > 2^n\)</span> ,所以阶乘阶比指数阶增长得更快,在 <span class="arithmatex">\(n\)</span> 较大时也是不可接受的。</p>
|
||||
|
@ -3397,7 +3397,7 @@
|
||||
<p>在计算机中,所有数据都是以二进制数的形式存储的,字符 <code>char</code> 也不例外。为了表示字符,我们需要建立一套“字符集”,规定每个字符和二进制数之间的一一对应关系。有了字符集之后,计算机就可以通过查表完成二进制数到字符的转换。</p>
|
||||
<h2 id="341-ascii">3.4.1 ASCII 字符集<a class="headerlink" href="#341-ascii" title="Permanent link">¶</a></h2>
|
||||
<p>「ASCII 码」是最早出现的字符集,全称为“美国标准信息交换代码”。它使用 7 位二进制数(即一个字节的低 7 位)表示一个字符,最多能够表示 128 个不同的字符。如图 3-6 所示,ASCII 码包括英文字母的大小写、数字 0 ~ 9、一些标点符号,以及一些控制字符(如换行符和制表符)。</p>
|
||||
<p><a class="glightbox" href="../character_encoding.assets/ascii_table.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="ASCII 码" src="../character_encoding.assets/ascii_table.png" /></a></p>
|
||||
<p><a class="glightbox" href="../character_encoding.assets/ascii_table.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="ASCII 码" class="animation-figure" src="../character_encoding.assets/ascii_table.png" /></a></p>
|
||||
<p align="center"> 图 3-6 ASCII 码 </p>
|
||||
|
||||
<p>然而,<strong>ASCII 码仅能够表示英文</strong>。随着计算机的全球化,诞生了一种能够表示更多语言的字符集「EASCII」。它在 ASCII 的 7 位基础上扩展到 8 位,能够表示 256 个不同的字符。</p>
|
||||
@ -3412,7 +3412,7 @@
|
||||
<p>自 1991 年发布以来,Unicode 不断扩充新的语言与字符。截止 2022 年 9 月,Unicode 已经包含 149186 个字符,包括各种语言的字符、符号、甚至是表情符号等。在庞大的 Unicode 字符集中,常用的字符占用 2 字节,有些生僻的字符占 3 字节甚至 4 字节。</p>
|
||||
<p>Unicode 是一种字符集标准,本质上是给每个字符分配一个编号(称为“码点”),<strong>但它并没有规定在计算机中如何存储这些字符码点</strong>。我们不禁会问:当多种长度的 Unicode 码点同时出现在同一个文本中时,系统如何解析字符?例如给定一个长度为 2 字节的编码,系统如何确认它是一个 2 字节的字符还是两个 1 字节的字符?</p>
|
||||
<p>对于以上问题,<strong>一种直接的解决方案是将所有字符存储为等长的编码</strong>。如图 3-7 所示,“Hello”中的每个字符占用 1 字节,“算法”中的每个字符占用 2 字节。我们可以通过高位填 0 ,将“Hello 算法”中的所有字符都编码为 2 字节长度。这样系统就可以每隔 2 字节解析一个字符,恢复出这个短语的内容了。</p>
|
||||
<p><a class="glightbox" href="../character_encoding.assets/unicode_hello_algo.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="Unicode 编码示例" src="../character_encoding.assets/unicode_hello_algo.png" /></a></p>
|
||||
<p><a class="glightbox" href="../character_encoding.assets/unicode_hello_algo.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="Unicode 编码示例" class="animation-figure" src="../character_encoding.assets/unicode_hello_algo.png" /></a></p>
|
||||
<p align="center"> 图 3-7 Unicode 编码示例 </p>
|
||||
|
||||
<p>然而 ASCII 码已经向我们证明,编码英文只需要 1 字节。若采用上述方案,英文文本占用空间的大小将会是 ASCII 编码下大小的两倍,非常浪费内存空间。因此,我们需要一种更加高效的 Unicode 编码方法。</p>
|
||||
@ -3426,7 +3426,7 @@
|
||||
<p>图 3-8 展示了“Hello算法”对应的 UTF-8 编码。观察发现,由于最高 <span class="arithmatex">\(n\)</span> 位都被设置为 <span class="arithmatex">\(1\)</span> ,因此系统可以通过读取最高位 <span class="arithmatex">\(1\)</span> 的个数来解析出字符的长度为 <span class="arithmatex">\(n\)</span> 。</p>
|
||||
<p>但为什么要将其余所有字节的高 2 位都设置为 <span class="arithmatex">\(10\)</span> 呢?实际上,这个 <span class="arithmatex">\(10\)</span> 能够起到校验符的作用。假设系统从一个错误的字节开始解析文本,字节头部的 <span class="arithmatex">\(10\)</span> 能够帮助系统快速的判断出异常。</p>
|
||||
<p>之所以将 <span class="arithmatex">\(10\)</span> 当作校验符,是因为在 UTF-8 编码规则下,不可能有字符的最高两位是 <span class="arithmatex">\(10\)</span> 。这个结论可以用反证法来证明:假设一个字符的最高两位是 <span class="arithmatex">\(10\)</span> ,说明该字符的长度为 <span class="arithmatex">\(1\)</span> ,对应 ASCII 码。而 ASCII 码的最高位应该是 <span class="arithmatex">\(0\)</span> ,与假设矛盾。</p>
|
||||
<p><a class="glightbox" href="../character_encoding.assets/utf-8_hello_algo.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="UTF-8 编码示例" src="../character_encoding.assets/utf-8_hello_algo.png" /></a></p>
|
||||
<p><a class="glightbox" href="../character_encoding.assets/utf-8_hello_algo.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="UTF-8 编码示例" class="animation-figure" src="../character_encoding.assets/utf-8_hello_algo.png" /></a></p>
|
||||
<p align="center"> 图 3-8 UTF-8 编码示例 </p>
|
||||
|
||||
<p>除了 UTF-8 之外,常见的编码方式还包括以下两种。</p>
|
||||
|
@ -3360,7 +3360,7 @@
|
||||
<li><strong>线性数据结构</strong>:数组、链表、栈、队列、哈希表。</li>
|
||||
<li><strong>非线性数据结构</strong>:树、堆、图、哈希表。</li>
|
||||
</ul>
|
||||
<p><a class="glightbox" href="../classification_of_data_structure.assets/classification_logic_structure.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="线性与非线性数据结构" src="../classification_of_data_structure.assets/classification_logic_structure.png" /></a></p>
|
||||
<p><a class="glightbox" href="../classification_of_data_structure.assets/classification_logic_structure.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="线性与非线性数据结构" class="animation-figure" src="../classification_of_data_structure.assets/classification_logic_structure.png" /></a></p>
|
||||
<p align="center"> 图 3-1 线性与非线性数据结构 </p>
|
||||
|
||||
<p>非线性数据结构可以进一步被划分为树形结构和网状结构。</p>
|
||||
@ -3373,12 +3373,12 @@
|
||||
<p>在计算机中,内存和硬盘是两种主要的存储硬件设备。硬盘主要用于长期存储数据,容量较大(通常可达到 TB 级别)、速度较慢。内存用于运行程序时暂存数据,速度较快,但容量较小(通常为 GB 级别)。</p>
|
||||
<p><strong>在算法运行过程中,相关数据都存储在内存中</strong>。图 3-2 展示了一个计算机内存条,其中每个黑色方块都包含一块内存空间。我们可以将内存想象成一个巨大的 Excel 表格,其中每个单元格都可以存储一定大小的数据,在算法运行时,所有数据都被存储在这些单元格中。</p>
|
||||
<p><strong>系统通过内存地址来访问目标位置的数据</strong>。如图 3-2 所示,计算机根据特定规则为表格中的每个单元格分配编号,确保每个内存空间都有唯一的内存地址。有了这些地址,程序便可以访问内存中的数据。</p>
|
||||
<p><a class="glightbox" href="../classification_of_data_structure.assets/computer_memory_location.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="内存条、内存空间、内存地址" src="../classification_of_data_structure.assets/computer_memory_location.png" /></a></p>
|
||||
<p><a class="glightbox" href="../classification_of_data_structure.assets/computer_memory_location.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="内存条、内存空间、内存地址" class="animation-figure" src="../classification_of_data_structure.assets/computer_memory_location.png" /></a></p>
|
||||
<p align="center"> 图 3-2 内存条、内存空间、内存地址 </p>
|
||||
|
||||
<p>内存是所有程序的共享资源,当某块内存被某个程序占用时,则无法被其他程序同时使用了。<strong>因此在数据结构与算法的设计中,内存资源是一个重要的考虑因素</strong>。比如,算法所占用的内存峰值不应超过系统剩余空闲内存;如果缺少连续大块的内存空间,那么所选用的数据结构必须能够存储在分散的内存空间内。</p>
|
||||
<p>如图 3-3 所示,<strong>物理结构反映了数据在计算机内存中的存储方式</strong>,可分为连续空间存储(数组)和分散空间存储(链表)。物理结构从底层决定了数据的访问、更新、增删等操作方法,同时在时间效率和空间效率方面呈现出互补的特点。</p>
|
||||
<p><a class="glightbox" href="../classification_of_data_structure.assets/classification_phisical_structure.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="连续空间存储与分散空间存储" src="../classification_of_data_structure.assets/classification_phisical_structure.png" /></a></p>
|
||||
<p><a class="glightbox" href="../classification_of_data_structure.assets/classification_phisical_structure.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="连续空间存储与分散空间存储" class="animation-figure" src="../classification_of_data_structure.assets/classification_phisical_structure.png" /></a></p>
|
||||
<p align="center"> 图 3-3 连续空间存储与分散空间存储 </p>
|
||||
|
||||
<p>值得说明的是,<strong>所有数据结构都是基于数组、链表或二者的组合实现的</strong>。例如,栈和队列既可以使用数组实现,也可以使用链表实现;而哈希表的实现可能同时包含数组和链表。</p>
|
||||
|
@ -3292,7 +3292,7 @@
|
||||
<!-- Page content -->
|
||||
<h1 id="3">第 3 章 数据结构<a class="headerlink" href="#3" title="Permanent link">¶</a></h1>
|
||||
<div class="center-table">
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_data_structure.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="数据结构" src="../assets/covers/chapter_data_structure.jpg" width="600" /></a></p>
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_data_structure.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="数据结构" class="cover-image" src="../assets/covers/chapter_data_structure.jpg" /></a></p>
|
||||
</div>
|
||||
<div class="admonition abstract">
|
||||
<p class="admonition-title">Abstract</p>
|
||||
|
@ -3365,7 +3365,7 @@
|
||||
<li><strong>补码</strong>:正数的补码与其原码相同,负数的补码是在其反码的基础上加 <span class="arithmatex">\(1\)</span> 。</li>
|
||||
</ul>
|
||||
<p>图 3-4 展示了原码、反码和补码之间的转换方法。</p>
|
||||
<p><a class="glightbox" href="../number_encoding.assets/1s_2s_complement.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="原码、反码与补码之间的相互转换" src="../number_encoding.assets/1s_2s_complement.png" /></a></p>
|
||||
<p><a class="glightbox" href="../number_encoding.assets/1s_2s_complement.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="原码、反码与补码之间的相互转换" class="animation-figure" src="../number_encoding.assets/1s_2s_complement.png" /></a></p>
|
||||
<p align="center"> 图 3-4 原码、反码与补码之间的相互转换 </p>
|
||||
|
||||
<p>「原码 true form」虽然最直观,但存在一些局限性。一方面,<strong>负数的原码不能直接用于运算</strong>。例如在原码下计算 <span class="arithmatex">\(1 + (-2)\)</span> ,得到的结果是 <span class="arithmatex">\(-3\)</span> ,这显然是不对的。</p>
|
||||
@ -3447,7 +3447,7 @@ b_{31} b_{30} b_{29} \ldots b_2 b_1 b_0
|
||||
(1 + \mathrm{N}) = & (1 + \sum_{i=1}^{23} b_{23-i} 2^{-i}) \subset [1, 2 - 2^{-23}]
|
||||
\end{aligned}
|
||||
\]</div>
|
||||
<p><a class="glightbox" href="../number_encoding.assets/ieee_754_float.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="IEEE 754 标准下的 float 的计算示例" src="../number_encoding.assets/ieee_754_float.png" /></a></p>
|
||||
<p><a class="glightbox" href="../number_encoding.assets/ieee_754_float.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="IEEE 754 标准下的 float 的计算示例" class="animation-figure" src="../number_encoding.assets/ieee_754_float.png" /></a></p>
|
||||
<p align="center"> 图 3-5 IEEE 754 标准下的 float 的计算示例 </p>
|
||||
|
||||
<p>观察图 3-5 ,给定一个示例数据 <span class="arithmatex">\(\mathrm{S} = 0\)</span> , <span class="arithmatex">\(\mathrm{E} = 124\)</span> ,<span class="arithmatex">\(\mathrm{N} = 2^{-2} + 2^{-3} = 0.375\)</span> ,则有:</p>
|
||||
|
@ -3369,7 +3369,7 @@
|
||||
<li>循环第 <code>1.</code> 和 <code>2.</code> 步,直至找到 <code>target</code> 或区间为空时返回。</li>
|
||||
</ol>
|
||||
<p>图 12-4 展示了在数组中二分查找元素 <span class="arithmatex">\(6\)</span> 的分治过程。</p>
|
||||
<p><a class="glightbox" href="../binary_search_recur.assets/binary_search_recur.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二分查找的分治过程" src="../binary_search_recur.assets/binary_search_recur.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_recur.assets/binary_search_recur.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二分查找的分治过程" class="animation-figure" src="../binary_search_recur.assets/binary_search_recur.png" /></a></p>
|
||||
<p align="center"> 图 12-4 二分查找的分治过程 </p>
|
||||
|
||||
<p>在实现代码中,我们声明一个递归函数 <code>dfs()</code> 来求解问题 <span class="arithmatex">\(f(i, j)\)</span> 。</p>
|
||||
|
@ -3384,7 +3384,7 @@
|
||||
<p class="admonition-title">Question</p>
|
||||
<p>给定一个二叉树的前序遍历 <code>preorder</code> 和中序遍历 <code>inorder</code> ,请从中构建二叉树,返回二叉树的根节点。假设二叉树中没有值重复的节点。</p>
|
||||
</div>
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/build_tree_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="构建二叉树的示例数据" src="../build_binary_tree_problem.assets/build_tree_example.png" /></a></p>
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/build_tree_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="构建二叉树的示例数据" class="animation-figure" src="../build_binary_tree_problem.assets/build_tree_example.png" /></a></p>
|
||||
<p align="center"> 图 12-5 构建二叉树的示例数据 </p>
|
||||
|
||||
<h3 id="1">1. 判断是否为分治问题<a class="headerlink" href="#1" title="Permanent link">¶</a></h3>
|
||||
@ -3407,7 +3407,7 @@
|
||||
<li>查找根节点 3 在 <code>inorder</code> 中的索引,利用该索引可将 <code>inorder</code> 划分为 <code>[ 9 | 3 | 1 2 7 ]</code> 。</li>
|
||||
<li>根据 <code>inorder</code> 划分结果,易得左子树和右子树的节点数量分别为 1 和 3 ,从而可将 <code>preorder</code> 划分为 <code>[ 3 | 9 | 2 1 7 ]</code> 。</li>
|
||||
</ol>
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/build_tree_preorder_inorder_division.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="在前序和中序遍历中划分子树" src="../build_binary_tree_problem.assets/build_tree_preorder_inorder_division.png" /></a></p>
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/build_tree_preorder_inorder_division.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="在前序和中序遍历中划分子树" class="animation-figure" src="../build_binary_tree_problem.assets/build_tree_preorder_inorder_division.png" /></a></p>
|
||||
<p align="center"> 图 12-6 在前序和中序遍历中划分子树 </p>
|
||||
|
||||
<h3 id="3">3. 基于变量描述子树区间<a class="headerlink" href="#3" title="Permanent link">¶</a></h3>
|
||||
@ -3449,7 +3449,7 @@
|
||||
</table>
|
||||
</div>
|
||||
<p>请注意,右子树根节点索引中的 <span class="arithmatex">\((m-l)\)</span> 的含义是“左子树的节点数量”,建议配合图 12-7 理解。</p>
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/build_tree_division_pointers.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="根节点和左右子树的索引区间表示" src="../build_binary_tree_problem.assets/build_tree_division_pointers.png" /></a></p>
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/build_tree_division_pointers.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="根节点和左右子树的索引区间表示" class="animation-figure" src="../build_binary_tree_problem.assets/build_tree_division_pointers.png" /></a></p>
|
||||
<p align="center"> 图 12-7 根节点和左右子树的索引区间表示 </p>
|
||||
|
||||
<h3 id="4">4. 代码实现<a class="headerlink" href="#4" title="Permanent link">¶</a></h3>
|
||||
@ -3812,38 +3812,38 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="2:9"><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" /><div class="tabbed-labels"><label for="__tabbed_2_1"><1></label><label for="__tabbed_2_2"><2></label><label for="__tabbed_2_3"><3></label><label for="__tabbed_2_4"><4></label><label for="__tabbed_2_5"><5></label><label for="__tabbed_2_6"><6></label><label for="__tabbed_2_7"><7></label><label for="__tabbed_2_8"><8></label><label for="__tabbed_2_9"><9></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/built_tree_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="构建二叉树的递归过程" src="../build_binary_tree_problem.assets/built_tree_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/built_tree_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="构建二叉树的递归过程" class="animation-figure" src="../build_binary_tree_problem.assets/built_tree_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/built_tree_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="built_tree_step2" src="../build_binary_tree_problem.assets/built_tree_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/built_tree_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="built_tree_step2" class="animation-figure" src="../build_binary_tree_problem.assets/built_tree_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/built_tree_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="built_tree_step3" src="../build_binary_tree_problem.assets/built_tree_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/built_tree_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="built_tree_step3" class="animation-figure" src="../build_binary_tree_problem.assets/built_tree_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/built_tree_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="built_tree_step4" src="../build_binary_tree_problem.assets/built_tree_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/built_tree_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="built_tree_step4" class="animation-figure" src="../build_binary_tree_problem.assets/built_tree_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/built_tree_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="built_tree_step5" src="../build_binary_tree_problem.assets/built_tree_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/built_tree_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="built_tree_step5" class="animation-figure" src="../build_binary_tree_problem.assets/built_tree_step5.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/built_tree_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="built_tree_step6" src="../build_binary_tree_problem.assets/built_tree_step6.png" /></a></p>
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/built_tree_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="built_tree_step6" class="animation-figure" src="../build_binary_tree_problem.assets/built_tree_step6.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/built_tree_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="built_tree_step7" src="../build_binary_tree_problem.assets/built_tree_step7.png" /></a></p>
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/built_tree_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="built_tree_step7" class="animation-figure" src="../build_binary_tree_problem.assets/built_tree_step7.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/built_tree_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="built_tree_step8" src="../build_binary_tree_problem.assets/built_tree_step8.png" /></a></p>
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/built_tree_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="built_tree_step8" class="animation-figure" src="../build_binary_tree_problem.assets/built_tree_step8.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/built_tree_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="built_tree_step9" src="../build_binary_tree_problem.assets/built_tree_step9.png" /></a></p>
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/built_tree_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="built_tree_step9" class="animation-figure" src="../build_binary_tree_problem.assets/built_tree_step9.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p align="center"> 图 12-8 构建二叉树的递归过程 </p>
|
||||
|
||||
<p>每个递归函数内的前序遍历 <code>preorder</code> 和中序遍历 <code>inorder</code> 的划分结果如图 12-9 所示。</p>
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/built_tree_overall.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="每个递归函数中的划分结果" src="../build_binary_tree_problem.assets/built_tree_overall.png" /></a></p>
|
||||
<p><a class="glightbox" href="../build_binary_tree_problem.assets/built_tree_overall.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="每个递归函数中的划分结果" class="animation-figure" src="../build_binary_tree_problem.assets/built_tree_overall.png" /></a></p>
|
||||
<p align="center"> 图 12-9 每个递归函数中的划分结果 </p>
|
||||
|
||||
<p>设树的节点数量为 <span class="arithmatex">\(n\)</span> ,初始化每一个节点(执行一个递归函数 <code>dfs()</code> )使用 <span class="arithmatex">\(O(1)\)</span> 时间。<strong>因此总体时间复杂度为 <span class="arithmatex">\(O(n)\)</span></strong> 。</p>
|
||||
|
@ -3416,7 +3416,7 @@
|
||||
<li><strong>分</strong>:递归地将原数组(原问题)划分为两个子数组(子问题),直到子数组只剩一个元素(最小子问题)。</li>
|
||||
<li><strong>治</strong>:从底至顶地将有序的子数组(子问题的解)进行合并,从而得到有序的原数组(原问题的解)。</li>
|
||||
</ol>
|
||||
<p><a class="glightbox" href="../divide_and_conquer.assets/divide_and_conquer_merge_sort.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="归并排序的分治策略" src="../divide_and_conquer.assets/divide_and_conquer_merge_sort.png" /></a></p>
|
||||
<p><a class="glightbox" href="../divide_and_conquer.assets/divide_and_conquer_merge_sort.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="归并排序的分治策略" class="animation-figure" src="../divide_and_conquer.assets/divide_and_conquer_merge_sort.png" /></a></p>
|
||||
<p align="center"> 图 12-1 归并排序的分治策略 </p>
|
||||
|
||||
<h2 id="1211">12.1.1 如何判断分治问题<a class="headerlink" href="#1211" title="Permanent link">¶</a></h2>
|
||||
@ -3440,7 +3440,7 @@
|
||||
<div class="arithmatex">\[
|
||||
O(n + (\frac{n}{2})^2 \times 2 + n) = O(\frac{n^2}{2} + 2n)
|
||||
\]</div>
|
||||
<p><a class="glightbox" href="../divide_and_conquer.assets/divide_and_conquer_bubble_sort.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="划分数组前后的冒泡排序" src="../divide_and_conquer.assets/divide_and_conquer_bubble_sort.png" /></a></p>
|
||||
<p><a class="glightbox" href="../divide_and_conquer.assets/divide_and_conquer_bubble_sort.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="划分数组前后的冒泡排序" class="animation-figure" src="../divide_and_conquer.assets/divide_and_conquer_bubble_sort.png" /></a></p>
|
||||
<p align="center"> 图 12-2 划分数组前后的冒泡排序 </p>
|
||||
|
||||
<p>接下来,我们计算以下不等式,其左边和右边分别为划分前和划分后的操作总数:</p>
|
||||
@ -3458,7 +3458,7 @@ n(n - 4) & > 0
|
||||
<p>我们知道,分治生成的子问题是相互独立的,<strong>因此通常可以并行解决</strong>。也就是说,分治不仅可以降低算法的时间复杂度,<strong>还有利于操作系统的并行优化</strong>。</p>
|
||||
<p>并行优化在多核或多处理器的环境中尤其有效,因为系统可以同时处理多个子问题,更加充分地利用计算资源,从而显著减少总体的运行时间。</p>
|
||||
<p>比如在图 12-3 所示的“桶排序”中,我们将海量的数据平均分配到各个桶中,则可所有桶的排序任务分散到各个计算单元,完成后再进行结果合并。</p>
|
||||
<p><a class="glightbox" href="../divide_and_conquer.assets/divide_and_conquer_parallel_computing.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="桶排序的并行计算" src="../divide_and_conquer.assets/divide_and_conquer_parallel_computing.png" /></a></p>
|
||||
<p><a class="glightbox" href="../divide_and_conquer.assets/divide_and_conquer_parallel_computing.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="桶排序的并行计算" class="animation-figure" src="../divide_and_conquer.assets/divide_and_conquer_parallel_computing.png" /></a></p>
|
||||
<p align="center"> 图 12-3 桶排序的并行计算 </p>
|
||||
|
||||
<h2 id="1213">12.1.3 分治常见应用<a class="headerlink" href="#1213" title="Permanent link">¶</a></h2>
|
||||
|
@ -3376,7 +3376,7 @@
|
||||
<li>小圆盘必须时刻位于大圆盘之上。</li>
|
||||
</ol>
|
||||
</div>
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="汉诺塔问题示例" src="../hanota_problem.assets/hanota_example.png" /></a></p>
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="汉诺塔问题示例" class="animation-figure" src="../hanota_problem.assets/hanota_example.png" /></a></p>
|
||||
<p align="center"> 图 12-10 汉诺塔问题示例 </p>
|
||||
|
||||
<p><strong>我们将规模为 <span class="arithmatex">\(i\)</span> 的汉诺塔问题记做 <span class="arithmatex">\(f(i)\)</span></strong> 。例如 <span class="arithmatex">\(f(3)\)</span> 代表将 <span class="arithmatex">\(3\)</span> 个圆盘从 <code>A</code> 移动至 <code>C</code> 的汉诺塔问题。</p>
|
||||
@ -3385,10 +3385,10 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="1:2"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1"><1></label><label for="__tabbed_1_2"><2></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_f1_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="规模为 1 问题的解" src="../hanota_problem.assets/hanota_f1_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_f1_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="规模为 1 问题的解" class="animation-figure" src="../hanota_problem.assets/hanota_f1_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_f1_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="hanota_f1_step2" src="../hanota_problem.assets/hanota_f1_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_f1_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="hanota_f1_step2" class="animation-figure" src="../hanota_problem.assets/hanota_f1_step2.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -3403,16 +3403,16 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="2:4"><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" /><div class="tabbed-labels"><label for="__tabbed_2_1"><1></label><label for="__tabbed_2_2"><2></label><label for="__tabbed_2_3"><3></label><label for="__tabbed_2_4"><4></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_f2_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="规模为 2 问题的解" src="../hanota_problem.assets/hanota_f2_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_f2_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="规模为 2 问题的解" class="animation-figure" src="../hanota_problem.assets/hanota_f2_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_f2_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="hanota_f2_step2" src="../hanota_problem.assets/hanota_f2_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_f2_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="hanota_f2_step2" class="animation-figure" src="../hanota_problem.assets/hanota_f2_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_f2_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="hanota_f2_step3" src="../hanota_problem.assets/hanota_f2_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_f2_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="hanota_f2_step3" class="animation-figure" src="../hanota_problem.assets/hanota_f2_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_f2_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="hanota_f2_step4" src="../hanota_problem.assets/hanota_f2_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_f2_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="hanota_f2_step4" class="animation-figure" src="../hanota_problem.assets/hanota_f2_step4.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -3430,16 +3430,16 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="3:4"><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" /><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></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_f3_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="规模为 3 问题的解" src="../hanota_problem.assets/hanota_f3_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_f3_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="规模为 3 问题的解" class="animation-figure" src="../hanota_problem.assets/hanota_f3_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_f3_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="hanota_f3_step2" src="../hanota_problem.assets/hanota_f3_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_f3_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="hanota_f3_step2" class="animation-figure" src="../hanota_problem.assets/hanota_f3_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_f3_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="hanota_f3_step3" src="../hanota_problem.assets/hanota_f3_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_f3_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="hanota_f3_step3" class="animation-figure" src="../hanota_problem.assets/hanota_f3_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_f3_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="hanota_f3_step4" src="../hanota_problem.assets/hanota_f3_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_f3_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="hanota_f3_step4" class="animation-figure" src="../hanota_problem.assets/hanota_f3_step4.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -3453,7 +3453,7 @@
|
||||
<li>将 <span class="arithmatex">\(n-1\)</span> 个圆盘借助 <code>A</code> 从 <code>B</code> 移至 <code>C</code> 。</li>
|
||||
</ol>
|
||||
<p>对于这两个子问题 <span class="arithmatex">\(f(n-1)\)</span> ,<strong>可以通过相同的方式进行递归划分</strong>,直至达到最小子问题 <span class="arithmatex">\(f(1)\)</span> 。而 <span class="arithmatex">\(f(1)\)</span> 的解是已知的,只需一次移动操作即可。</p>
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_divide_and_conquer.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="汉诺塔问题的分治策略" src="../hanota_problem.assets/hanota_divide_and_conquer.png" /></a></p>
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_divide_and_conquer.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="汉诺塔问题的分治策略" class="animation-figure" src="../hanota_problem.assets/hanota_divide_and_conquer.png" /></a></p>
|
||||
<p align="center"> 图 12-14 汉诺塔问题的分治策略 </p>
|
||||
|
||||
<h3 id="3">3. 代码实现<a class="headerlink" href="#3" title="Permanent link">¶</a></h3>
|
||||
@ -3826,7 +3826,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<p>如图 12-15 所示,汉诺塔问题形成一个高度为 <span class="arithmatex">\(n\)</span> 的递归树,每个节点代表一个子问题、对应一个开启的 <code>dfs()</code> 函数,<strong>因此时间复杂度为 <span class="arithmatex">\(O(2^n)\)</span> ,空间复杂度为 <span class="arithmatex">\(O(n)\)</span></strong> 。</p>
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_recursive_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="汉诺塔问题的递归树" src="../hanota_problem.assets/hanota_recursive_tree.png" /></a></p>
|
||||
<p><a class="glightbox" href="../hanota_problem.assets/hanota_recursive_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="汉诺塔问题的递归树" class="animation-figure" src="../hanota_problem.assets/hanota_recursive_tree.png" /></a></p>
|
||||
<p align="center"> 图 12-15 汉诺塔问题的递归树 </p>
|
||||
|
||||
<div class="admonition quote">
|
||||
|
@ -3292,7 +3292,7 @@
|
||||
<!-- Page content -->
|
||||
<h1 id="12">第 12 章 分治<a class="headerlink" href="#12" title="Permanent link">¶</a></h1>
|
||||
<div class="center-table">
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_divide_and_conquer.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="分治" src="../assets/covers/chapter_divide_and_conquer.jpg" width="600" /></a></p>
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_divide_and_conquer.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="分治" class="cover-image" src="../assets/covers/chapter_divide_and_conquer.jpg" /></a></p>
|
||||
</div>
|
||||
<div class="admonition abstract">
|
||||
<p class="admonition-title">Abstract</p>
|
||||
|
@ -3366,7 +3366,7 @@
|
||||
<p>给定一个楼梯,你每步可以上 <span class="arithmatex">\(1\)</span> 阶或者 <span class="arithmatex">\(2\)</span> 阶,每一阶楼梯上都贴有一个非负整数,表示你在该台阶所需要付出的代价。给定一个非负整数数组 <span class="arithmatex">\(cost\)</span> ,其中 <span class="arithmatex">\(cost[i]\)</span> 表示在第 <span class="arithmatex">\(i\)</span> 个台阶需要付出的代价,<span class="arithmatex">\(cost[0]\)</span> 为地面起始点。请计算最少需要付出多少代价才能到达顶部?</p>
|
||||
</div>
|
||||
<p>如图 14-6 所示,若第 <span class="arithmatex">\(1\)</span>、<span class="arithmatex">\(2\)</span>、<span class="arithmatex">\(3\)</span> 阶的代价分别为 <span class="arithmatex">\(1\)</span>、<span class="arithmatex">\(10\)</span>、<span class="arithmatex">\(1\)</span> ,则从地面爬到第 <span class="arithmatex">\(3\)</span> 阶的最小代价为 <span class="arithmatex">\(2\)</span> 。</p>
|
||||
<p><a class="glightbox" href="../dp_problem_features.assets/min_cost_cs_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="爬到第 3 阶的最小代价" src="../dp_problem_features.assets/min_cost_cs_example.png" /></a></p>
|
||||
<p><a class="glightbox" href="../dp_problem_features.assets/min_cost_cs_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="爬到第 3 阶的最小代价" class="animation-figure" src="../dp_problem_features.assets/min_cost_cs_example.png" /></a></p>
|
||||
<p align="center"> 图 14-6 爬到第 3 阶的最小代价 </p>
|
||||
|
||||
<p>设 <span class="arithmatex">\(dp[i]\)</span> 为爬到第 <span class="arithmatex">\(i\)</span> 阶累计付出的代价,由于第 <span class="arithmatex">\(i\)</span> 阶只可能从 <span class="arithmatex">\(i - 1\)</span> 阶或 <span class="arithmatex">\(i - 2\)</span> 阶走来,因此 <span class="arithmatex">\(dp[i]\)</span> 只可能等于 <span class="arithmatex">\(dp[i - 1] + cost[i]\)</span> 或 <span class="arithmatex">\(dp[i - 2] + cost[i]\)</span> 。为了尽可能减少代价,我们应该选择两者中较小的那一个:</p>
|
||||
@ -3616,7 +3616,7 @@ dp[i] = \min(dp[i-1], dp[i-2]) + cost[i]
|
||||
</div>
|
||||
</div>
|
||||
<p>图 14-7 展示了以上代码的动态规划过程。</p>
|
||||
<p><a class="glightbox" href="../dp_problem_features.assets/min_cost_cs_dp.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="爬楼梯最小代价的动态规划过程" src="../dp_problem_features.assets/min_cost_cs_dp.png" /></a></p>
|
||||
<p><a class="glightbox" href="../dp_problem_features.assets/min_cost_cs_dp.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="爬楼梯最小代价的动态规划过程" class="animation-figure" src="../dp_problem_features.assets/min_cost_cs_dp.png" /></a></p>
|
||||
<p align="center"> 图 14-7 爬楼梯最小代价的动态规划过程 </p>
|
||||
|
||||
<p>本题也可以进行空间优化,将一维压缩至零维,使得空间复杂度从 <span class="arithmatex">\(O(n)\)</span> 降低至 <span class="arithmatex">\(O(1)\)</span> 。</p>
|
||||
@ -3834,7 +3834,7 @@ dp[i] = \min(dp[i-1], dp[i-2]) + cost[i]
|
||||
<p>给定一个共有 <span class="arithmatex">\(n\)</span> 阶的楼梯,你每步可以上 <span class="arithmatex">\(1\)</span> 阶或者 <span class="arithmatex">\(2\)</span> 阶,<strong>但不能连续两轮跳 <span class="arithmatex">\(1\)</span> 阶</strong>,请问有多少种方案可以爬到楼顶。</p>
|
||||
</div>
|
||||
<p>例如图 14-8 ,爬上第 <span class="arithmatex">\(3\)</span> 阶仅剩 <span class="arithmatex">\(2\)</span> 种可行方案,其中连续三次跳 <span class="arithmatex">\(1\)</span> 阶的方案不满足约束条件,因此被舍弃。</p>
|
||||
<p><a class="glightbox" href="../dp_problem_features.assets/climbing_stairs_constraint_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="带约束爬到第 3 阶的方案数量" src="../dp_problem_features.assets/climbing_stairs_constraint_example.png" /></a></p>
|
||||
<p><a class="glightbox" href="../dp_problem_features.assets/climbing_stairs_constraint_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="带约束爬到第 3 阶的方案数量" class="animation-figure" src="../dp_problem_features.assets/climbing_stairs_constraint_example.png" /></a></p>
|
||||
<p align="center"> 图 14-8 带约束爬到第 3 阶的方案数量 </p>
|
||||
|
||||
<p>在该问题中,如果上一轮是跳 <span class="arithmatex">\(1\)</span> 阶上来的,那么下一轮就必须跳 <span class="arithmatex">\(2\)</span> 阶。这意味着,<strong>下一步选择不能由当前状态(当前楼梯阶数)独立决定,还和前一个状态(上轮楼梯阶数)有关</strong>。</p>
|
||||
@ -3851,7 +3851,7 @@ dp[i, 1] = dp[i-1, 2] \\
|
||||
dp[i, 2] = dp[i-2, 1] + dp[i-2, 2]
|
||||
\end{cases}
|
||||
\]</div>
|
||||
<p><a class="glightbox" href="../dp_problem_features.assets/climbing_stairs_constraint_state_transfer.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="考虑约束下的递推关系" src="../dp_problem_features.assets/climbing_stairs_constraint_state_transfer.png" /></a></p>
|
||||
<p><a class="glightbox" href="../dp_problem_features.assets/climbing_stairs_constraint_state_transfer.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="考虑约束下的递推关系" class="animation-figure" src="../dp_problem_features.assets/climbing_stairs_constraint_state_transfer.png" /></a></p>
|
||||
<p align="center"> 图 14-9 考虑约束下的递推关系 </p>
|
||||
|
||||
<p>最终,返回 <span class="arithmatex">\(dp[n, 1] + dp[n, 2]\)</span> 即可,两者之和代表爬到第 <span class="arithmatex">\(n\)</span> 阶的方案总数。</p>
|
||||
|
@ -3448,14 +3448,14 @@
|
||||
<p>给定一个 <span class="arithmatex">\(n \times m\)</span> 的二维网格 <code>grid</code> ,网格中的每个单元格包含一个非负整数,表示该单元格的代价。机器人以左上角单元格为起始点,每次只能向下或者向右移动一步,直至到达右下角单元格。请返回从左上角到右下角的最小路径和。</p>
|
||||
</div>
|
||||
<p>图 14-10 展示了一个例子,给定网格的最小路径和为 <span class="arithmatex">\(13\)</span> 。</p>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="最小路径和示例数据" src="../dp_solution_pipeline.assets/min_path_sum_example.png" /></a></p>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="最小路径和示例数据" class="animation-figure" src="../dp_solution_pipeline.assets/min_path_sum_example.png" /></a></p>
|
||||
<p align="center"> 图 14-10 最小路径和示例数据 </p>
|
||||
|
||||
<p><strong>第一步:思考每轮的决策,定义状态,从而得到 <span class="arithmatex">\(dp\)</span> 表</strong></p>
|
||||
<p>本题的每一轮的决策就是从当前格子向下或向右一步。设当前格子的行列索引为 <span class="arithmatex">\([i, j]\)</span> ,则向下或向右走一步后,索引变为 <span class="arithmatex">\([i+1, j]\)</span> 或 <span class="arithmatex">\([i, j+1]\)</span> 。因此,状态应包含行索引和列索引两个变量,记为 <span class="arithmatex">\([i, j]\)</span> 。</p>
|
||||
<p>状态 <span class="arithmatex">\([i, j]\)</span> 对应的子问题为:从起始点 <span class="arithmatex">\([0, 0]\)</span> 走到 <span class="arithmatex">\([i, j]\)</span> 的最小路径和,解记为 <span class="arithmatex">\(dp[i, j]\)</span> 。</p>
|
||||
<p>至此,我们就得到了图 14-11 所示的二维 <span class="arithmatex">\(dp\)</span> 矩阵,其尺寸与输入网格 <span class="arithmatex">\(grid\)</span> 相同。</p>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_solution_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="状态定义与 dp 表" src="../dp_solution_pipeline.assets/min_path_sum_solution_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_solution_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="状态定义与 dp 表" class="animation-figure" src="../dp_solution_pipeline.assets/min_path_sum_solution_step1.png" /></a></p>
|
||||
<p align="center"> 图 14-11 状态定义与 dp 表 </p>
|
||||
|
||||
<div class="admonition note">
|
||||
@ -3469,7 +3469,7 @@
|
||||
<div class="arithmatex">\[
|
||||
dp[i, j] = \min(dp[i-1, j], dp[i, j-1]) + grid[i, j]
|
||||
\]</div>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_solution_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="最优子结构与状态转移方程" src="../dp_solution_pipeline.assets/min_path_sum_solution_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_solution_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="最优子结构与状态转移方程" class="animation-figure" src="../dp_solution_pipeline.assets/min_path_sum_solution_step2.png" /></a></p>
|
||||
<p align="center"> 图 14-12 最优子结构与状态转移方程 </p>
|
||||
|
||||
<div class="admonition note">
|
||||
@ -3480,7 +3480,7 @@ dp[i, j] = \min(dp[i-1, j], dp[i, j-1]) + grid[i, j]
|
||||
<p><strong>第三步:确定边界条件和状态转移顺序</strong></p>
|
||||
<p>在本题中,首行的状态只能从其左边的状态得来,首列的状态只能从其上边的状态得来,因此首行 <span class="arithmatex">\(i = 0\)</span> 和首列 <span class="arithmatex">\(j = 0\)</span> 是边界条件。</p>
|
||||
<p>如图 14-13 所示,由于每个格子是由其左方格子和上方格子转移而来,因此我们使用采用循环来遍历矩阵,外循环遍历各行、内循环遍历各列。</p>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_solution_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="边界条件与状态转移顺序" src="../dp_solution_pipeline.assets/min_path_sum_solution_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_solution_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="边界条件与状态转移顺序" class="animation-figure" src="../dp_solution_pipeline.assets/min_path_sum_solution_step3.png" /></a></p>
|
||||
<p align="center"> 图 14-13 边界条件与状态转移顺序 </p>
|
||||
|
||||
<div class="admonition note">
|
||||
@ -3733,7 +3733,7 @@ dp[i, j] = \min(dp[i-1, j], dp[i, j-1]) + grid[i, j]
|
||||
</div>
|
||||
<p>图 14-14 给出了以 <span class="arithmatex">\(dp[2, 1]\)</span> 为根节点的递归树,其中包含一些重叠子问题,其数量会随着网格 <code>grid</code> 的尺寸变大而急剧增多。</p>
|
||||
<p>本质上看,造成重叠子问题的原因为:<strong>存在多条路径可以从左上角到达某一单元格</strong>。</p>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dfs.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="暴力搜索递归树" src="../dp_solution_pipeline.assets/min_path_sum_dfs.png" /></a></p>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dfs.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="暴力搜索递归树" class="animation-figure" src="../dp_solution_pipeline.assets/min_path_sum_dfs.png" /></a></p>
|
||||
<p align="center"> 图 14-14 暴力搜索递归树 </p>
|
||||
|
||||
<p>每个状态都有向下和向右两种选择,从左上角走到右下角总共需要 <span class="arithmatex">\(m + n - 2\)</span> 步,所以最差时间复杂度为 <span class="arithmatex">\(O(2^{m + n})\)</span> 。请注意,这种计算方式未考虑临近网格边界的情况,当到达网络边界时只剩下一种选择。因此实际的路径数量会少一些。</p>
|
||||
@ -4037,7 +4037,7 @@ dp[i, j] = \min(dp[i-1, j], dp[i, j-1]) + grid[i, j]
|
||||
</div>
|
||||
</div>
|
||||
<p>如图 14-15 所示,在引入记忆化后,所有子问题的解只需计算一次,因此时间复杂度取决于状态总数,即网格尺寸 <span class="arithmatex">\(O(nm)\)</span> 。</p>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dfs_mem.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="记忆化搜索递归树" src="../dp_solution_pipeline.assets/min_path_sum_dfs_mem.png" /></a></p>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dfs_mem.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="记忆化搜索递归树" class="animation-figure" src="../dp_solution_pipeline.assets/min_path_sum_dfs_mem.png" /></a></p>
|
||||
<p align="center"> 图 14-15 记忆化搜索递归树 </p>
|
||||
|
||||
<h3 id="3">3. 方法三:动态规划<a class="headerlink" href="#3" title="Permanent link">¶</a></h3>
|
||||
@ -4356,40 +4356,40 @@ dp[i, j] = \min(dp[i-1, j], dp[i, j-1]) + grid[i, j]
|
||||
<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"><1></label><label for="__tabbed_4_2"><2></label><label for="__tabbed_4_3"><3></label><label for="__tabbed_4_4"><4></label><label for="__tabbed_4_5"><5></label><label for="__tabbed_4_6"><6></label><label for="__tabbed_4_7"><7></label><label for="__tabbed_4_8"><8></label><label for="__tabbed_4_9"><9></label><label for="__tabbed_4_10"><10></label><label for="__tabbed_4_11"><11></label><label for="__tabbed_4_12"><12></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="最小路径和的动态规划过程" src="../dp_solution_pipeline.assets/min_path_sum_dp_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="最小路径和的动态规划过程" class="animation-figure" src="../dp_solution_pipeline.assets/min_path_sum_dp_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="min_path_sum_dp_step2" src="../dp_solution_pipeline.assets/min_path_sum_dp_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="min_path_sum_dp_step2" class="animation-figure" src="../dp_solution_pipeline.assets/min_path_sum_dp_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="min_path_sum_dp_step3" src="../dp_solution_pipeline.assets/min_path_sum_dp_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="min_path_sum_dp_step3" class="animation-figure" src="../dp_solution_pipeline.assets/min_path_sum_dp_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="min_path_sum_dp_step4" src="../dp_solution_pipeline.assets/min_path_sum_dp_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="min_path_sum_dp_step4" class="animation-figure" src="../dp_solution_pipeline.assets/min_path_sum_dp_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="min_path_sum_dp_step5" src="../dp_solution_pipeline.assets/min_path_sum_dp_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="min_path_sum_dp_step5" class="animation-figure" src="../dp_solution_pipeline.assets/min_path_sum_dp_step5.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="min_path_sum_dp_step6" src="../dp_solution_pipeline.assets/min_path_sum_dp_step6.png" /></a></p>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="min_path_sum_dp_step6" class="animation-figure" src="../dp_solution_pipeline.assets/min_path_sum_dp_step6.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="min_path_sum_dp_step7" src="../dp_solution_pipeline.assets/min_path_sum_dp_step7.png" /></a></p>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="min_path_sum_dp_step7" class="animation-figure" src="../dp_solution_pipeline.assets/min_path_sum_dp_step7.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="min_path_sum_dp_step8" src="../dp_solution_pipeline.assets/min_path_sum_dp_step8.png" /></a></p>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="min_path_sum_dp_step8" class="animation-figure" src="../dp_solution_pipeline.assets/min_path_sum_dp_step8.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="min_path_sum_dp_step9" src="../dp_solution_pipeline.assets/min_path_sum_dp_step9.png" /></a></p>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="min_path_sum_dp_step9" class="animation-figure" src="../dp_solution_pipeline.assets/min_path_sum_dp_step9.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="min_path_sum_dp_step10" src="../dp_solution_pipeline.assets/min_path_sum_dp_step10.png" /></a></p>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="min_path_sum_dp_step10" class="animation-figure" src="../dp_solution_pipeline.assets/min_path_sum_dp_step10.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step11.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="min_path_sum_dp_step11" src="../dp_solution_pipeline.assets/min_path_sum_dp_step11.png" /></a></p>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step11.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="min_path_sum_dp_step11" class="animation-figure" src="../dp_solution_pipeline.assets/min_path_sum_dp_step11.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step12.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="min_path_sum_dp_step12" src="../dp_solution_pipeline.assets/min_path_sum_dp_step12.png" /></a></p>
|
||||
<p><a class="glightbox" href="../dp_solution_pipeline.assets/min_path_sum_dp_step12.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="min_path_sum_dp_step12" class="animation-figure" src="../dp_solution_pipeline.assets/min_path_sum_dp_step12.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3373,13 +3373,13 @@
|
||||
<p>你可以在一个字符串中进行三种编辑操作:插入一个字符、删除一个字符、替换字符为任意一个字符。</p>
|
||||
</div>
|
||||
<p>如图 14-27 所示,将 <code>kitten</code> 转换为 <code>sitting</code> 需要编辑 3 步,包括 2 次替换操作与 1 次添加操作;将 <code>hello</code> 转换为 <code>algo</code> 需要 3 步,包括 2 次替换操作和 1 次删除操作。</p>
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="编辑距离的示例数据" src="../edit_distance_problem.assets/edit_distance_example.png" /></a></p>
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="编辑距离的示例数据" class="animation-figure" src="../edit_distance_problem.assets/edit_distance_example.png" /></a></p>
|
||||
<p align="center"> 图 14-27 编辑距离的示例数据 </p>
|
||||
|
||||
<p><strong>编辑距离问题可以很自然地用决策树模型来解释</strong>。字符串对应树节点,一轮决策(一次编辑操作)对应树的一条边。</p>
|
||||
<p>如图 14-28 所示,在不限制操作的情况下,每个节点都可以派生出许多条边,每条边对应一种操作,这意味着从 <code>hello</code> 转换到 <code>algo</code> 有许多种可能的路径。</p>
|
||||
<p>从决策树的角度看,本题的目标是求解节点 <code>hello</code> 和节点 <code>algo</code> 之间的最短路径。</p>
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_decision_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="基于决策树模型表示编辑距离问题" src="../edit_distance_problem.assets/edit_distance_decision_tree.png" /></a></p>
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_decision_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="基于决策树模型表示编辑距离问题" class="animation-figure" src="../edit_distance_problem.assets/edit_distance_decision_tree.png" /></a></p>
|
||||
<p align="center"> 图 14-28 基于决策树模型表示编辑距离问题 </p>
|
||||
|
||||
<h3 id="1">1. 动态规划思路<a class="headerlink" href="#1" title="Permanent link">¶</a></h3>
|
||||
@ -3400,7 +3400,7 @@
|
||||
<li>删除 <span class="arithmatex">\(s[i-1]\)</span> ,则剩余子问题 <span class="arithmatex">\(dp[i-1, j]\)</span> 。</li>
|
||||
<li>将 <span class="arithmatex">\(s[i-1]\)</span> 替换为 <span class="arithmatex">\(t[j-1]\)</span> ,则剩余子问题 <span class="arithmatex">\(dp[i-1, j-1]\)</span> 。</li>
|
||||
</ol>
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_state_transfer.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="编辑距离的状态转移" src="../edit_distance_problem.assets/edit_distance_state_transfer.png" /></a></p>
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_state_transfer.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="编辑距离的状态转移" class="animation-figure" src="../edit_distance_problem.assets/edit_distance_state_transfer.png" /></a></p>
|
||||
<p align="center"> 图 14-29 编辑距离的状态转移 </p>
|
||||
|
||||
<p>根据以上分析,可得最优子结构:<span class="arithmatex">\(dp[i, j]\)</span> 的最少编辑步数等于 <span class="arithmatex">\(dp[i, j-1]\)</span>、<span class="arithmatex">\(dp[i-1, j]\)</span>、<span class="arithmatex">\(dp[i-1, j-1]\)</span> 三者中的最少编辑步数,再加上本次的编辑步数 <span class="arithmatex">\(1\)</span> 。对应的状态转移方程为:</p>
|
||||
@ -3765,49 +3765,49 @@ dp[i, j] = dp[i-1, j-1]
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="2:15"><input checked="checked" id="__tabbed_2_1" name="__tabbed_2" type="radio" /><input id="__tabbed_2_2" name="__tabbed_2" type="radio" /><input id="__tabbed_2_3" name="__tabbed_2" type="radio" /><input id="__tabbed_2_4" name="__tabbed_2" type="radio" /><input id="__tabbed_2_5" name="__tabbed_2" type="radio" /><input id="__tabbed_2_6" name="__tabbed_2" type="radio" /><input id="__tabbed_2_7" name="__tabbed_2" type="radio" /><input id="__tabbed_2_8" name="__tabbed_2" type="radio" /><input id="__tabbed_2_9" name="__tabbed_2" type="radio" /><input id="__tabbed_2_10" name="__tabbed_2" type="radio" /><input id="__tabbed_2_11" name="__tabbed_2" type="radio" /><input id="__tabbed_2_12" name="__tabbed_2" type="radio" /><input id="__tabbed_2_13" name="__tabbed_2" type="radio" /><input id="__tabbed_2_14" name="__tabbed_2" type="radio" /><input id="__tabbed_2_15" name="__tabbed_2" type="radio" /><div class="tabbed-labels"><label for="__tabbed_2_1"><1></label><label for="__tabbed_2_2"><2></label><label for="__tabbed_2_3"><3></label><label for="__tabbed_2_4"><4></label><label for="__tabbed_2_5"><5></label><label for="__tabbed_2_6"><6></label><label for="__tabbed_2_7"><7></label><label for="__tabbed_2_8"><8></label><label for="__tabbed_2_9"><9></label><label for="__tabbed_2_10"><10></label><label for="__tabbed_2_11"><11></label><label for="__tabbed_2_12"><12></label><label for="__tabbed_2_13"><13></label><label for="__tabbed_2_14"><14></label><label for="__tabbed_2_15"><15></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="编辑距离的动态规划过程" src="../edit_distance_problem.assets/edit_distance_dp_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="编辑距离的动态规划过程" class="animation-figure" src="../edit_distance_problem.assets/edit_distance_dp_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step2" src="../edit_distance_problem.assets/edit_distance_dp_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step2" class="animation-figure" src="../edit_distance_problem.assets/edit_distance_dp_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step3" src="../edit_distance_problem.assets/edit_distance_dp_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step3" class="animation-figure" src="../edit_distance_problem.assets/edit_distance_dp_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step4" src="../edit_distance_problem.assets/edit_distance_dp_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step4" class="animation-figure" src="../edit_distance_problem.assets/edit_distance_dp_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step5" src="../edit_distance_problem.assets/edit_distance_dp_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step5" class="animation-figure" src="../edit_distance_problem.assets/edit_distance_dp_step5.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step6" src="../edit_distance_problem.assets/edit_distance_dp_step6.png" /></a></p>
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step6" class="animation-figure" src="../edit_distance_problem.assets/edit_distance_dp_step6.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step7" src="../edit_distance_problem.assets/edit_distance_dp_step7.png" /></a></p>
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step7" class="animation-figure" src="../edit_distance_problem.assets/edit_distance_dp_step7.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step8" src="../edit_distance_problem.assets/edit_distance_dp_step8.png" /></a></p>
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step8" class="animation-figure" src="../edit_distance_problem.assets/edit_distance_dp_step8.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step9" src="../edit_distance_problem.assets/edit_distance_dp_step9.png" /></a></p>
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step9" class="animation-figure" src="../edit_distance_problem.assets/edit_distance_dp_step9.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step10" src="../edit_distance_problem.assets/edit_distance_dp_step10.png" /></a></p>
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step10" class="animation-figure" src="../edit_distance_problem.assets/edit_distance_dp_step10.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step11.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step11" src="../edit_distance_problem.assets/edit_distance_dp_step11.png" /></a></p>
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step11.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step11" class="animation-figure" src="../edit_distance_problem.assets/edit_distance_dp_step11.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step12.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step12" src="../edit_distance_problem.assets/edit_distance_dp_step12.png" /></a></p>
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step12.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step12" class="animation-figure" src="../edit_distance_problem.assets/edit_distance_dp_step12.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step13.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step13" src="../edit_distance_problem.assets/edit_distance_dp_step13.png" /></a></p>
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step13.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step13" class="animation-figure" src="../edit_distance_problem.assets/edit_distance_dp_step13.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step14.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step14" src="../edit_distance_problem.assets/edit_distance_dp_step14.png" /></a></p>
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step14.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step14" class="animation-figure" src="../edit_distance_problem.assets/edit_distance_dp_step14.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step15.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step15" src="../edit_distance_problem.assets/edit_distance_dp_step15.png" /></a></p>
|
||||
<p><a class="glightbox" href="../edit_distance_problem.assets/edit_distance_dp_step15.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="edit_distance_dp_step15" class="animation-figure" src="../edit_distance_problem.assets/edit_distance_dp_step15.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3292,7 +3292,7 @@
|
||||
<!-- Page content -->
|
||||
<h1 id="14">第 14 章 动态规划<a class="headerlink" href="#14" title="Permanent link">¶</a></h1>
|
||||
<div class="center-table">
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_dynamic_programming.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="动态规划" src="../assets/covers/chapter_dynamic_programming.jpg" width="600" /></a></p>
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_dynamic_programming.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="动态规划" class="cover-image" src="../assets/covers/chapter_dynamic_programming.jpg" /></a></p>
|
||||
</div>
|
||||
<div class="admonition abstract">
|
||||
<p class="admonition-title">Abstract</p>
|
||||
|
@ -3387,7 +3387,7 @@
|
||||
<p>给定一个共有 <span class="arithmatex">\(n\)</span> 阶的楼梯,你每步可以上 <span class="arithmatex">\(1\)</span> 阶或者 <span class="arithmatex">\(2\)</span> 阶,请问有多少种方案可以爬到楼顶。</p>
|
||||
</div>
|
||||
<p>如图 14-1 所示,对于一个 <span class="arithmatex">\(3\)</span> 阶楼梯,共有 <span class="arithmatex">\(3\)</span> 种方案可以爬到楼顶。</p>
|
||||
<p><a class="glightbox" href="../intro_to_dynamic_programming.assets/climbing_stairs_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="爬到第 3 阶的方案数量" src="../intro_to_dynamic_programming.assets/climbing_stairs_example.png" /></a></p>
|
||||
<p><a class="glightbox" href="../intro_to_dynamic_programming.assets/climbing_stairs_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="爬到第 3 阶的方案数量" class="animation-figure" src="../intro_to_dynamic_programming.assets/climbing_stairs_example.png" /></a></p>
|
||||
<p align="center"> 图 14-1 爬到第 3 阶的方案数量 </p>
|
||||
|
||||
<p>本题的目标是求解方案数量,<strong>我们可以考虑通过回溯来穷举所有可能性</strong>。具体来说,将爬楼梯想象为一个多轮选择的过程:从地面出发,每轮选择上 <span class="arithmatex">\(1\)</span> 阶或 <span class="arithmatex">\(2\)</span> 阶,每当到达楼梯顶部时就将方案数量加 <span class="arithmatex">\(1\)</span> ,当越过楼梯顶部时就将其剪枝。</p>
|
||||
@ -3748,7 +3748,7 @@ dp[i-1], dp[i-2], \dots, dp[2], dp[1]
|
||||
dp[i] = dp[i-1] + dp[i-2]
|
||||
\]</div>
|
||||
<p>这意味着在爬楼梯问题中,各个子问题之间存在递推关系,<strong>原问题的解可以由子问题的解构建得来</strong>。图 14-2 展示了该递推关系。</p>
|
||||
<p><a class="glightbox" href="../intro_to_dynamic_programming.assets/climbing_stairs_state_transfer.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="方案数量递推关系" src="../intro_to_dynamic_programming.assets/climbing_stairs_state_transfer.png" /></a></p>
|
||||
<p><a class="glightbox" href="../intro_to_dynamic_programming.assets/climbing_stairs_state_transfer.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="方案数量递推关系" class="animation-figure" src="../intro_to_dynamic_programming.assets/climbing_stairs_state_transfer.png" /></a></p>
|
||||
<p align="center"> 图 14-2 方案数量递推关系 </p>
|
||||
|
||||
<p>我们可以根据递推公式得到暴力搜索解法。以 <span class="arithmatex">\(dp[n]\)</span> 为起始点,<strong>递归地将一个较大问题拆解为两个较小问题的和</strong>,直至到达最小子问题 <span class="arithmatex">\(dp[1]\)</span> 和 <span class="arithmatex">\(dp[2]\)</span> 时返回。其中,最小子问题的解是已知的,即 <span class="arithmatex">\(dp[1] = 1\)</span>、<span class="arithmatex">\(dp[2] = 2\)</span> ,表示爬到第 <span class="arithmatex">\(1\)</span>、<span class="arithmatex">\(2\)</span> 阶分别有 <span class="arithmatex">\(1\)</span>、<span class="arithmatex">\(2\)</span> 种方案。</p>
|
||||
@ -3959,7 +3959,7 @@ dp[i] = dp[i-1] + dp[i-2]
|
||||
</div>
|
||||
</div>
|
||||
<p>图 14-3 展示了暴力搜索形成的递归树。对于问题 <span class="arithmatex">\(dp[n]\)</span> ,其递归树的深度为 <span class="arithmatex">\(n\)</span> ,时间复杂度为 <span class="arithmatex">\(O(2^n)\)</span> 。指数阶属于爆炸式增长,如果我们输入一个比较大的 <span class="arithmatex">\(n\)</span> ,则会陷入漫长的等待之中。</p>
|
||||
<p><a class="glightbox" href="../intro_to_dynamic_programming.assets/climbing_stairs_dfs_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="爬楼梯对应递归树" src="../intro_to_dynamic_programming.assets/climbing_stairs_dfs_tree.png" /></a></p>
|
||||
<p><a class="glightbox" href="../intro_to_dynamic_programming.assets/climbing_stairs_dfs_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="爬楼梯对应递归树" class="animation-figure" src="../intro_to_dynamic_programming.assets/climbing_stairs_dfs_tree.png" /></a></p>
|
||||
<p align="center"> 图 14-3 爬楼梯对应递归树 </p>
|
||||
|
||||
<p>观察图 14-3 ,<strong>指数阶的时间复杂度是由于“重叠子问题”导致的</strong>。例如 <span class="arithmatex">\(dp[9]\)</span> 被分解为 <span class="arithmatex">\(dp[8]\)</span> 和 <span class="arithmatex">\(dp[7]\)</span> ,<span class="arithmatex">\(dp[8]\)</span> 被分解为 <span class="arithmatex">\(dp[7]\)</span> 和 <span class="arithmatex">\(dp[6]\)</span> ,两者都包含子问题 <span class="arithmatex">\(dp[7]\)</span> 。</p>
|
||||
@ -4269,7 +4269,7 @@ dp[i] = dp[i-1] + dp[i-2]
|
||||
</div>
|
||||
</div>
|
||||
<p>观察图 14-4 ,<strong>经过记忆化处理后,所有重叠子问题都只需被计算一次,时间复杂度被优化至 <span class="arithmatex">\(O(n)\)</span></strong> ,这是一个巨大的飞跃。</p>
|
||||
<p><a class="glightbox" href="../intro_to_dynamic_programming.assets/climbing_stairs_dfs_memo_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="记忆化搜索对应递归树" src="../intro_to_dynamic_programming.assets/climbing_stairs_dfs_memo_tree.png" /></a></p>
|
||||
<p><a class="glightbox" href="../intro_to_dynamic_programming.assets/climbing_stairs_dfs_memo_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="记忆化搜索对应递归树" class="animation-figure" src="../intro_to_dynamic_programming.assets/climbing_stairs_dfs_memo_tree.png" /></a></p>
|
||||
<p align="center"> 图 14-4 记忆化搜索对应递归树 </p>
|
||||
|
||||
<h2 id="1413">14.1.3 方法三:动态规划<a class="headerlink" href="#1413" title="Permanent link">¶</a></h2>
|
||||
@ -4497,7 +4497,7 @@ dp[i] = dp[i-1] + dp[i-2]
|
||||
</div>
|
||||
</div>
|
||||
<p>图 14-5 模拟了以上代码的执行过程。</p>
|
||||
<p><a class="glightbox" href="../intro_to_dynamic_programming.assets/climbing_stairs_dp.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="爬楼梯的动态规划过程" src="../intro_to_dynamic_programming.assets/climbing_stairs_dp.png" /></a></p>
|
||||
<p><a class="glightbox" href="../intro_to_dynamic_programming.assets/climbing_stairs_dp.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="爬楼梯的动态规划过程" class="animation-figure" src="../intro_to_dynamic_programming.assets/climbing_stairs_dp.png" /></a></p>
|
||||
<p align="center"> 图 14-5 爬楼梯的动态规划过程 </p>
|
||||
|
||||
<p>与回溯算法一样,动态规划也使用“状态”概念来表示问题求解的某个特定阶段,每个状态都对应一个子问题以及相应的局部最优解。例如,爬楼梯问题的状态定义为当前所在楼梯阶数 <span class="arithmatex">\(i\)</span> 。</p>
|
||||
|
@ -3387,7 +3387,7 @@
|
||||
<p>给定 <span class="arithmatex">\(n\)</span> 个物品,第 <span class="arithmatex">\(i\)</span> 个物品的重量为 <span class="arithmatex">\(wgt[i-1]\)</span>、价值为 <span class="arithmatex">\(val[i-1]\)</span> ,和一个容量为 <span class="arithmatex">\(cap\)</span> 的背包。每个物品只能选择一次,问在不超过背包容量下能放入物品的最大价值。</p>
|
||||
</div>
|
||||
<p>观察图 14-17 ,由于物品编号 <span class="arithmatex">\(i\)</span> 从 <span class="arithmatex">\(1\)</span> 开始计数,数组索引从 <span class="arithmatex">\(0\)</span> 开始计数,因此物品 <span class="arithmatex">\(i\)</span> 对应重量 <span class="arithmatex">\(wgt[i-1]\)</span> 和价值 <span class="arithmatex">\(val[i-1]\)</span> 。</p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="0-1 背包的示例数据" src="../knapsack_problem.assets/knapsack_example.png" /></a></p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="0-1 背包的示例数据" class="animation-figure" src="../knapsack_problem.assets/knapsack_example.png" /></a></p>
|
||||
<p align="center"> 图 14-17 0-1 背包的示例数据 </p>
|
||||
|
||||
<p>我们可以将 0-1 背包问题看作是一个由 <span class="arithmatex">\(n\)</span> 轮决策组成的过程,每个物体都有不放入和放入两种决策,因此该问题是满足决策树模型的。</p>
|
||||
@ -3655,7 +3655,7 @@ dp[i, c] = \max(dp[i-1, c], dp[i-1, c - wgt[i-1]] + val[i-1])
|
||||
</div>
|
||||
<p>如图 14-18 所示,由于每个物品都会产生不选和选两条搜索分支,因此时间复杂度为 <span class="arithmatex">\(O(2^n)\)</span> 。</p>
|
||||
<p>观察递归树,容易发现其中存在重叠子问题,例如 <span class="arithmatex">\(dp[1, 10]\)</span> 等。而当物品较多、背包容量较大,尤其是相同重量的物品较多时,重叠子问题的数量将会大幅增多。</p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dfs.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="0-1 背包的暴力搜索递归树" src="../knapsack_problem.assets/knapsack_dfs.png" /></a></p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dfs.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="0-1 背包的暴力搜索递归树" class="animation-figure" src="../knapsack_problem.assets/knapsack_dfs.png" /></a></p>
|
||||
<p align="center"> 图 14-18 0-1 背包的暴力搜索递归树 </p>
|
||||
|
||||
<h3 id="2">2. 方法二:记忆化搜索<a class="headerlink" href="#2" title="Permanent link">¶</a></h3>
|
||||
@ -3966,7 +3966,7 @@ dp[i, c] = \max(dp[i-1, c], dp[i-1, c - wgt[i-1]] + val[i-1])
|
||||
</div>
|
||||
</div>
|
||||
<p>图 14-19 展示了在记忆化递归中被剪掉的搜索分支。</p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dfs_mem.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="0-1 背包的记忆化搜索递归树" src="../knapsack_problem.assets/knapsack_dfs_mem.png" /></a></p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dfs_mem.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="0-1 背包的记忆化搜索递归树" class="animation-figure" src="../knapsack_problem.assets/knapsack_dfs_mem.png" /></a></p>
|
||||
<p align="center"> 图 14-19 0-1 背包的记忆化搜索递归树 </p>
|
||||
|
||||
<h3 id="3">3. 方法三:动态规划<a class="headerlink" href="#3" title="Permanent link">¶</a></h3>
|
||||
@ -4257,46 +4257,46 @@ dp[i, c] = \max(dp[i-1, c], dp[i-1, c - wgt[i-1]] + val[i-1])
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="4:14"><input checked="checked" id="__tabbed_4_1" name="__tabbed_4" type="radio" /><input id="__tabbed_4_2" name="__tabbed_4" type="radio" /><input id="__tabbed_4_3" name="__tabbed_4" type="radio" /><input id="__tabbed_4_4" name="__tabbed_4" type="radio" /><input id="__tabbed_4_5" name="__tabbed_4" type="radio" /><input id="__tabbed_4_6" name="__tabbed_4" type="radio" /><input id="__tabbed_4_7" name="__tabbed_4" type="radio" /><input id="__tabbed_4_8" name="__tabbed_4" type="radio" /><input id="__tabbed_4_9" name="__tabbed_4" type="radio" /><input id="__tabbed_4_10" name="__tabbed_4" type="radio" /><input id="__tabbed_4_11" name="__tabbed_4" type="radio" /><input id="__tabbed_4_12" name="__tabbed_4" type="radio" /><input id="__tabbed_4_13" name="__tabbed_4" type="radio" /><input id="__tabbed_4_14" name="__tabbed_4" type="radio" /><div class="tabbed-labels"><label for="__tabbed_4_1"><1></label><label for="__tabbed_4_2"><2></label><label for="__tabbed_4_3"><3></label><label for="__tabbed_4_4"><4></label><label for="__tabbed_4_5"><5></label><label for="__tabbed_4_6"><6></label><label for="__tabbed_4_7"><7></label><label for="__tabbed_4_8"><8></label><label for="__tabbed_4_9"><9></label><label for="__tabbed_4_10"><10></label><label for="__tabbed_4_11"><11></label><label for="__tabbed_4_12"><12></label><label for="__tabbed_4_13"><13></label><label for="__tabbed_4_14"><14></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="0-1 背包的动态规划过程" src="../knapsack_problem.assets/knapsack_dp_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="0-1 背包的动态规划过程" class="animation-figure" src="../knapsack_problem.assets/knapsack_dp_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step2" src="../knapsack_problem.assets/knapsack_dp_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step2" class="animation-figure" src="../knapsack_problem.assets/knapsack_dp_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step3" src="../knapsack_problem.assets/knapsack_dp_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step3" class="animation-figure" src="../knapsack_problem.assets/knapsack_dp_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step4" src="../knapsack_problem.assets/knapsack_dp_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step4" class="animation-figure" src="../knapsack_problem.assets/knapsack_dp_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step5" src="../knapsack_problem.assets/knapsack_dp_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step5" class="animation-figure" src="../knapsack_problem.assets/knapsack_dp_step5.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step6" src="../knapsack_problem.assets/knapsack_dp_step6.png" /></a></p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step6" class="animation-figure" src="../knapsack_problem.assets/knapsack_dp_step6.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step7" src="../knapsack_problem.assets/knapsack_dp_step7.png" /></a></p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step7" class="animation-figure" src="../knapsack_problem.assets/knapsack_dp_step7.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step8" src="../knapsack_problem.assets/knapsack_dp_step8.png" /></a></p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step8" class="animation-figure" src="../knapsack_problem.assets/knapsack_dp_step8.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step9" src="../knapsack_problem.assets/knapsack_dp_step9.png" /></a></p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step9" class="animation-figure" src="../knapsack_problem.assets/knapsack_dp_step9.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step10" src="../knapsack_problem.assets/knapsack_dp_step10.png" /></a></p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step10" class="animation-figure" src="../knapsack_problem.assets/knapsack_dp_step10.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step11.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step11" src="../knapsack_problem.assets/knapsack_dp_step11.png" /></a></p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step11.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step11" class="animation-figure" src="../knapsack_problem.assets/knapsack_dp_step11.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step12.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step12" src="../knapsack_problem.assets/knapsack_dp_step12.png" /></a></p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step12.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step12" class="animation-figure" src="../knapsack_problem.assets/knapsack_dp_step12.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step13.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step13" src="../knapsack_problem.assets/knapsack_dp_step13.png" /></a></p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step13.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step13" class="animation-figure" src="../knapsack_problem.assets/knapsack_dp_step13.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step14.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step14" src="../knapsack_problem.assets/knapsack_dp_step14.png" /></a></p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_step14.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_step14" class="animation-figure" src="../knapsack_problem.assets/knapsack_dp_step14.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -4313,22 +4313,22 @@ dp[i, c] = \max(dp[i-1, c], dp[i-1, c - wgt[i-1]] + val[i-1])
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="5:6"><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" /><div class="tabbed-labels"><label for="__tabbed_5_1"><1></label><label for="__tabbed_5_2"><2></label><label for="__tabbed_5_3"><3></label><label for="__tabbed_5_4"><4></label><label for="__tabbed_5_5"><5></label><label for="__tabbed_5_6"><6></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_comp_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="0-1 背包的空间优化后的动态规划过程" src="../knapsack_problem.assets/knapsack_dp_comp_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_comp_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="0-1 背包的空间优化后的动态规划过程" class="animation-figure" src="../knapsack_problem.assets/knapsack_dp_comp_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_comp_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_comp_step2" src="../knapsack_problem.assets/knapsack_dp_comp_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_comp_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_comp_step2" class="animation-figure" src="../knapsack_problem.assets/knapsack_dp_comp_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_comp_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_comp_step3" src="../knapsack_problem.assets/knapsack_dp_comp_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_comp_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_comp_step3" class="animation-figure" src="../knapsack_problem.assets/knapsack_dp_comp_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_comp_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_comp_step4" src="../knapsack_problem.assets/knapsack_dp_comp_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_comp_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_comp_step4" class="animation-figure" src="../knapsack_problem.assets/knapsack_dp_comp_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_comp_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_comp_step5" src="../knapsack_problem.assets/knapsack_dp_comp_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_comp_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_comp_step5" class="animation-figure" src="../knapsack_problem.assets/knapsack_dp_comp_step5.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_comp_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_comp_step6" src="../knapsack_problem.assets/knapsack_dp_comp_step6.png" /></a></p>
|
||||
<p><a class="glightbox" href="../knapsack_problem.assets/knapsack_dp_comp_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="knapsack_dp_comp_step6" class="animation-figure" src="../knapsack_problem.assets/knapsack_dp_comp_step6.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3534,7 +3534,7 @@
|
||||
<p class="admonition-title">Question</p>
|
||||
<p>给定 <span class="arithmatex">\(n\)</span> 个物品,第 <span class="arithmatex">\(i\)</span> 个物品的重量为 <span class="arithmatex">\(wgt[i-1]\)</span>、价值为 <span class="arithmatex">\(val[i-1]\)</span> ,和一个容量为 <span class="arithmatex">\(cap\)</span> 的背包。<strong>每个物品可以重复选取</strong>,问在不超过背包容量下能放入物品的最大价值。</p>
|
||||
</div>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/unbounded_knapsack_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="完全背包问题的示例数据" src="../unbounded_knapsack_problem.assets/unbounded_knapsack_example.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/unbounded_knapsack_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="完全背包问题的示例数据" class="animation-figure" src="../unbounded_knapsack_problem.assets/unbounded_knapsack_example.png" /></a></p>
|
||||
<p align="center"> 图 14-22 完全背包问题的示例数据 </p>
|
||||
|
||||
<h3 id="1">1. 动态规划思路<a class="headerlink" href="#1" title="Permanent link">¶</a></h3>
|
||||
@ -3842,22 +3842,22 @@ dp[i, c] = \max(dp[i-1, c], dp[i, c - wgt[i-1]] + val[i-1])
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="2:6"><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" /><div class="tabbed-labels"><label for="__tabbed_2_1"><1></label><label for="__tabbed_2_2"><2></label><label for="__tabbed_2_3"><3></label><label for="__tabbed_2_4"><4></label><label for="__tabbed_2_5"><5></label><label for="__tabbed_2_6"><6></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="完全背包的空间优化后的动态规划过程" src="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="完全背包的空间优化后的动态规划过程" class="animation-figure" src="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="unbounded_knapsack_dp_comp_step2" src="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="unbounded_knapsack_dp_comp_step2" class="animation-figure" src="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="unbounded_knapsack_dp_comp_step3" src="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="unbounded_knapsack_dp_comp_step3" class="animation-figure" src="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="unbounded_knapsack_dp_comp_step4" src="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="unbounded_knapsack_dp_comp_step4" class="animation-figure" src="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="unbounded_knapsack_dp_comp_step5" src="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="unbounded_knapsack_dp_comp_step5" class="animation-figure" src="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step5.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="unbounded_knapsack_dp_comp_step6" src="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step6.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="unbounded_knapsack_dp_comp_step6" class="animation-figure" src="../unbounded_knapsack_problem.assets/unbounded_knapsack_dp_comp_step6.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -4140,7 +4140,7 @@ dp[i, c] = \max(dp[i-1, c], dp[i, c - wgt[i-1]] + val[i-1])
|
||||
<p class="admonition-title">Question</p>
|
||||
<p>给定 <span class="arithmatex">\(n\)</span> 种硬币,第 <span class="arithmatex">\(i\)</span> 种硬币的面值为 <span class="arithmatex">\(coins[i - 1]\)</span> ,目标金额为 <span class="arithmatex">\(amt\)</span> ,<strong>每种硬币可以重复选取</strong>,问能够凑出目标金额的最少硬币个数。如果无法凑出目标金额则返回 <span class="arithmatex">\(-1\)</span> 。</p>
|
||||
</div>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="零钱兑换问题的示例数据" src="../unbounded_knapsack_problem.assets/coin_change_example.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="零钱兑换问题的示例数据" class="animation-figure" src="../unbounded_knapsack_problem.assets/coin_change_example.png" /></a></p>
|
||||
<p align="center"> 图 14-24 零钱兑换问题的示例数据 </p>
|
||||
|
||||
<h3 id="1_1">1. 动态规划思路<a class="headerlink" href="#1_1" title="Permanent link">¶</a></h3>
|
||||
@ -4511,49 +4511,49 @@ dp[i, a] = \min(dp[i-1, a], dp[i, a - coins[i-1]] + 1)
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="5:15"><input checked="checked" id="__tabbed_5_1" name="__tabbed_5" type="radio" /><input id="__tabbed_5_2" name="__tabbed_5" type="radio" /><input id="__tabbed_5_3" name="__tabbed_5" type="radio" /><input id="__tabbed_5_4" name="__tabbed_5" type="radio" /><input id="__tabbed_5_5" name="__tabbed_5" type="radio" /><input id="__tabbed_5_6" name="__tabbed_5" type="radio" /><input id="__tabbed_5_7" name="__tabbed_5" type="radio" /><input id="__tabbed_5_8" name="__tabbed_5" type="radio" /><input id="__tabbed_5_9" name="__tabbed_5" type="radio" /><input id="__tabbed_5_10" name="__tabbed_5" type="radio" /><input id="__tabbed_5_11" name="__tabbed_5" type="radio" /><input id="__tabbed_5_12" name="__tabbed_5" type="radio" /><input id="__tabbed_5_13" name="__tabbed_5" type="radio" /><input id="__tabbed_5_14" name="__tabbed_5" type="radio" /><input id="__tabbed_5_15" name="__tabbed_5" type="radio" /><div class="tabbed-labels"><label for="__tabbed_5_1"><1></label><label for="__tabbed_5_2"><2></label><label for="__tabbed_5_3"><3></label><label for="__tabbed_5_4"><4></label><label for="__tabbed_5_5"><5></label><label for="__tabbed_5_6"><6></label><label for="__tabbed_5_7"><7></label><label for="__tabbed_5_8"><8></label><label for="__tabbed_5_9"><9></label><label for="__tabbed_5_10"><10></label><label for="__tabbed_5_11"><11></label><label for="__tabbed_5_12"><12></label><label for="__tabbed_5_13"><13></label><label for="__tabbed_5_14"><14></label><label for="__tabbed_5_15"><15></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="零钱兑换问题的动态规划过程" src="../unbounded_knapsack_problem.assets/coin_change_dp_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="零钱兑换问题的动态规划过程" class="animation-figure" src="../unbounded_knapsack_problem.assets/coin_change_dp_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step2" src="../unbounded_knapsack_problem.assets/coin_change_dp_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step2" class="animation-figure" src="../unbounded_knapsack_problem.assets/coin_change_dp_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step3" src="../unbounded_knapsack_problem.assets/coin_change_dp_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step3" class="animation-figure" src="../unbounded_knapsack_problem.assets/coin_change_dp_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step4" src="../unbounded_knapsack_problem.assets/coin_change_dp_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step4" class="animation-figure" src="../unbounded_knapsack_problem.assets/coin_change_dp_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step5" src="../unbounded_knapsack_problem.assets/coin_change_dp_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step5" class="animation-figure" src="../unbounded_knapsack_problem.assets/coin_change_dp_step5.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step6" src="../unbounded_knapsack_problem.assets/coin_change_dp_step6.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step6" class="animation-figure" src="../unbounded_knapsack_problem.assets/coin_change_dp_step6.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step7" src="../unbounded_knapsack_problem.assets/coin_change_dp_step7.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step7" class="animation-figure" src="../unbounded_knapsack_problem.assets/coin_change_dp_step7.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step8" src="../unbounded_knapsack_problem.assets/coin_change_dp_step8.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step8" class="animation-figure" src="../unbounded_knapsack_problem.assets/coin_change_dp_step8.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step9" src="../unbounded_knapsack_problem.assets/coin_change_dp_step9.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step9" class="animation-figure" src="../unbounded_knapsack_problem.assets/coin_change_dp_step9.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step10" src="../unbounded_knapsack_problem.assets/coin_change_dp_step10.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step10" class="animation-figure" src="../unbounded_knapsack_problem.assets/coin_change_dp_step10.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step11.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step11" src="../unbounded_knapsack_problem.assets/coin_change_dp_step11.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step11.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step11" class="animation-figure" src="../unbounded_knapsack_problem.assets/coin_change_dp_step11.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step12.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step12" src="../unbounded_knapsack_problem.assets/coin_change_dp_step12.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step12.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step12" class="animation-figure" src="../unbounded_knapsack_problem.assets/coin_change_dp_step12.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step13.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step13" src="../unbounded_knapsack_problem.assets/coin_change_dp_step13.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step13.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step13" class="animation-figure" src="../unbounded_knapsack_problem.assets/coin_change_dp_step13.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step14.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step14" src="../unbounded_knapsack_problem.assets/coin_change_dp_step14.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step14.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step14" class="animation-figure" src="../unbounded_knapsack_problem.assets/coin_change_dp_step14.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step15.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step15" src="../unbounded_knapsack_problem.assets/coin_change_dp_step15.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_dp_step15.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="coin_change_dp_step15" class="animation-figure" src="../unbounded_knapsack_problem.assets/coin_change_dp_step15.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -4870,7 +4870,7 @@ dp[i, a] = \min(dp[i-1, a], dp[i, a - coins[i-1]] + 1)
|
||||
<p class="admonition-title">Question</p>
|
||||
<p>给定 <span class="arithmatex">\(n\)</span> 种硬币,第 <span class="arithmatex">\(i\)</span> 种硬币的面值为 <span class="arithmatex">\(coins[i - 1]\)</span> ,目标金额为 <span class="arithmatex">\(amt\)</span> ,每种硬币可以重复选取,<strong>问在凑出目标金额的硬币组合数量</strong>。</p>
|
||||
</div>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_ii_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="零钱兑换问题 II 的示例数据" src="../unbounded_knapsack_problem.assets/coin_change_ii_example.png" /></a></p>
|
||||
<p><a class="glightbox" href="../unbounded_knapsack_problem.assets/coin_change_ii_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="零钱兑换问题 II 的示例数据" class="animation-figure" src="../unbounded_knapsack_problem.assets/coin_change_ii_example.png" /></a></p>
|
||||
<p align="center"> 图 14-26 零钱兑换问题 II 的示例数据 </p>
|
||||
|
||||
<h3 id="1_2">1. 动态规划思路<a class="headerlink" href="#1_2" title="Permanent link">¶</a></h3>
|
||||
|
@ -3415,7 +3415,7 @@ G & = \{ V, E \} \newline
|
||||
\end{aligned}
|
||||
\]</div>
|
||||
<p>如果将顶点看作节点,将边看作连接各个节点的引用(指针),我们就可以将图看作是一种从链表拓展而来的数据结构。如图 9-1 所示,<strong>相较于线性关系(链表)和分治关系(树),网络关系(图)的自由度更高</strong>,从而更为复杂。</p>
|
||||
<p><a class="glightbox" href="../graph.assets/linkedlist_tree_graph.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="链表、树、图之间的关系" src="../graph.assets/linkedlist_tree_graph.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph.assets/linkedlist_tree_graph.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="链表、树、图之间的关系" class="animation-figure" src="../graph.assets/linkedlist_tree_graph.png" /></a></p>
|
||||
<p align="center"> 图 9-1 链表、树、图之间的关系 </p>
|
||||
|
||||
<h2 id="911">9.1.1 图常见类型与术语<a class="headerlink" href="#911" title="Permanent link">¶</a></h2>
|
||||
@ -3424,7 +3424,7 @@ G & = \{ V, E \} \newline
|
||||
<li>在无向图中,边表示两顶点之间的“双向”连接关系,例如微信或 QQ 中的“好友关系”。</li>
|
||||
<li>在有向图中,边具有方向性,即 <span class="arithmatex">\(A \rightarrow B\)</span> 和 <span class="arithmatex">\(A \leftarrow B\)</span> 两个方向的边是相互独立的,例如微博或抖音上的“关注”与“被关注”关系。</li>
|
||||
</ul>
|
||||
<p><a class="glightbox" href="../graph.assets/directed_graph.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="有向图与无向图" src="../graph.assets/directed_graph.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph.assets/directed_graph.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="有向图与无向图" class="animation-figure" src="../graph.assets/directed_graph.png" /></a></p>
|
||||
<p align="center"> 图 9-2 有向图与无向图 </p>
|
||||
|
||||
<p>根据所有顶点是否连通,可分为图 9-3 所示的「连通图 connected graph」和「非连通图 disconnected graph」。</p>
|
||||
@ -3432,11 +3432,11 @@ G & = \{ V, E \} \newline
|
||||
<li>对于连通图,从某个顶点出发,可以到达其余任意顶点。</li>
|
||||
<li>对于非连通图,从某个顶点出发,至少有一个顶点无法到达。</li>
|
||||
</ul>
|
||||
<p><a class="glightbox" href="../graph.assets/connected_graph.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="连通图与非连通图" src="../graph.assets/connected_graph.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph.assets/connected_graph.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="连通图与非连通图" class="animation-figure" src="../graph.assets/connected_graph.png" /></a></p>
|
||||
<p align="center"> 图 9-3 连通图与非连通图 </p>
|
||||
|
||||
<p>我们还可以为边添加“权重”变量,从而得到图 9-4 所示的「有权图 weighted graph」。例如在王者荣耀等手游中,系统会根据共同游戏时间来计算玩家之间的“亲密度”,这种亲密度网络就可以用有权图来表示。</p>
|
||||
<p><a class="glightbox" href="../graph.assets/weighted_graph.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="有权图与无权图" src="../graph.assets/weighted_graph.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph.assets/weighted_graph.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="有权图与无权图" class="animation-figure" src="../graph.assets/weighted_graph.png" /></a></p>
|
||||
<p align="center"> 图 9-4 有权图与无权图 </p>
|
||||
|
||||
<p>图数据结构包含以下常用术语。</p>
|
||||
@ -3450,7 +3450,7 @@ G & = \{ V, E \} \newline
|
||||
<h3 id="1">1. 邻接矩阵<a class="headerlink" href="#1" title="Permanent link">¶</a></h3>
|
||||
<p>设图的顶点数量为 <span class="arithmatex">\(n\)</span> ,「邻接矩阵 adjacency matrix」使用一个 <span class="arithmatex">\(n \times n\)</span> 大小的矩阵来表示图,每一行(列)代表一个顶点,矩阵元素代表边,用 <span class="arithmatex">\(1\)</span> 或 <span class="arithmatex">\(0\)</span> 表示两个顶点之间是否存在边。</p>
|
||||
<p>如图 9-5 所示,设邻接矩阵为 <span class="arithmatex">\(M\)</span>、顶点列表为 <span class="arithmatex">\(V\)</span> ,那么矩阵元素 <span class="arithmatex">\(M[i, j] = 1\)</span> 表示顶点 <span class="arithmatex">\(V[i]\)</span> 到顶点 <span class="arithmatex">\(V[j]\)</span> 之间存在边,反之 <span class="arithmatex">\(M[i, j] = 0\)</span> 表示两顶点之间无边。</p>
|
||||
<p><a class="glightbox" href="../graph.assets/adjacency_matrix.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="图的邻接矩阵表示" src="../graph.assets/adjacency_matrix.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph.assets/adjacency_matrix.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="图的邻接矩阵表示" class="animation-figure" src="../graph.assets/adjacency_matrix.png" /></a></p>
|
||||
<p align="center"> 图 9-5 图的邻接矩阵表示 </p>
|
||||
|
||||
<p>邻接矩阵具有以下特性。</p>
|
||||
@ -3462,7 +3462,7 @@ G & = \{ V, E \} \newline
|
||||
<p>使用邻接矩阵表示图时,我们可以直接访问矩阵元素以获取边,因此增删查操作的效率很高,时间复杂度均为 <span class="arithmatex">\(O(1)\)</span> 。然而,矩阵的空间复杂度为 <span class="arithmatex">\(O(n^2)\)</span> ,内存占用较多。</p>
|
||||
<h3 id="2">2. 邻接表<a class="headerlink" href="#2" title="Permanent link">¶</a></h3>
|
||||
<p>「邻接表 adjacency list」使用 <span class="arithmatex">\(n\)</span> 个链表来表示图,链表节点表示顶点。第 <span class="arithmatex">\(i\)</span> 条链表对应顶点 <span class="arithmatex">\(i\)</span> ,其中存储了该顶点的所有邻接顶点(即与该顶点相连的顶点)。图 9-6 展示了一个使用邻接表存储的图的示例。</p>
|
||||
<p><a class="glightbox" href="../graph.assets/adjacency_list.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="图的邻接表表示" src="../graph.assets/adjacency_list.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph.assets/adjacency_list.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="图的邻接表表示" class="animation-figure" src="../graph.assets/adjacency_list.png" /></a></p>
|
||||
<p align="center"> 图 9-6 图的邻接表表示 </p>
|
||||
|
||||
<p>邻接表仅存储实际存在的边,而边的总数通常远小于 <span class="arithmatex">\(n^2\)</span> ,因此它更加节省空间。然而,在邻接表中需要通过遍历链表来查找边,因此其时间效率不如邻接矩阵。</p>
|
||||
|
@ -3378,19 +3378,19 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="1:5"><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" /><div class="tabbed-labels"><label for="__tabbed_1_1">初始化邻接矩阵</label><label for="__tabbed_1_2">添加边</label><label for="__tabbed_1_3">删除边</label><label for="__tabbed_1_4">添加顶点</label><label for="__tabbed_1_5">删除顶点</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_operations.assets/adjacency_matrix_initialization.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="邻接矩阵的初始化、增删边、增删顶点" src="../graph_operations.assets/adjacency_matrix_initialization.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_operations.assets/adjacency_matrix_initialization.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="邻接矩阵的初始化、增删边、增删顶点" class="animation-figure" src="../graph_operations.assets/adjacency_matrix_initialization.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_operations.assets/adjacency_matrix_add_edge.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="adjacency_matrix_add_edge" src="../graph_operations.assets/adjacency_matrix_add_edge.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_operations.assets/adjacency_matrix_add_edge.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="adjacency_matrix_add_edge" class="animation-figure" src="../graph_operations.assets/adjacency_matrix_add_edge.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_operations.assets/adjacency_matrix_remove_edge.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="adjacency_matrix_remove_edge" src="../graph_operations.assets/adjacency_matrix_remove_edge.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_operations.assets/adjacency_matrix_remove_edge.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="adjacency_matrix_remove_edge" class="animation-figure" src="../graph_operations.assets/adjacency_matrix_remove_edge.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_operations.assets/adjacency_matrix_add_vertex.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="adjacency_matrix_add_vertex" src="../graph_operations.assets/adjacency_matrix_add_vertex.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_operations.assets/adjacency_matrix_add_vertex.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="adjacency_matrix_add_vertex" class="animation-figure" src="../graph_operations.assets/adjacency_matrix_add_vertex.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_operations.assets/adjacency_matrix_remove_vertex.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="adjacency_matrix_remove_vertex" src="../graph_operations.assets/adjacency_matrix_remove_vertex.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_operations.assets/adjacency_matrix_remove_vertex.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="adjacency_matrix_remove_vertex" class="animation-figure" src="../graph_operations.assets/adjacency_matrix_remove_vertex.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -4400,19 +4400,19 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="3:5"><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" /><div class="tabbed-labels"><label for="__tabbed_3_1">初始化邻接表</label><label for="__tabbed_3_2">添加边</label><label for="__tabbed_3_3">删除边</label><label for="__tabbed_3_4">添加顶点</label><label for="__tabbed_3_5">删除顶点</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_operations.assets/adjacency_list_initialization.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="邻接表的初始化、增删边、增删顶点" src="../graph_operations.assets/adjacency_list_initialization.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_operations.assets/adjacency_list_initialization.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="邻接表的初始化、增删边、增删顶点" class="animation-figure" src="../graph_operations.assets/adjacency_list_initialization.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_operations.assets/adjacency_list_add_edge.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="adjacency_list_add_edge" src="../graph_operations.assets/adjacency_list_add_edge.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_operations.assets/adjacency_list_add_edge.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="adjacency_list_add_edge" class="animation-figure" src="../graph_operations.assets/adjacency_list_add_edge.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_operations.assets/adjacency_list_remove_edge.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="adjacency_list_remove_edge" src="../graph_operations.assets/adjacency_list_remove_edge.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_operations.assets/adjacency_list_remove_edge.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="adjacency_list_remove_edge" class="animation-figure" src="../graph_operations.assets/adjacency_list_remove_edge.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_operations.assets/adjacency_list_add_vertex.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="adjacency_list_add_vertex" src="../graph_operations.assets/adjacency_list_add_vertex.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_operations.assets/adjacency_list_add_vertex.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="adjacency_list_add_vertex" class="animation-figure" src="../graph_operations.assets/adjacency_list_add_vertex.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_operations.assets/adjacency_list_remove_vertex.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="adjacency_list_remove_vertex" src="../graph_operations.assets/adjacency_list_remove_vertex.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_operations.assets/adjacency_list_remove_vertex.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="adjacency_list_remove_vertex" class="animation-figure" src="../graph_operations.assets/adjacency_list_remove_vertex.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3436,7 +3436,7 @@
|
||||
<p>图和树都需要应用搜索算法来实现遍历操作。图的遍历方式可分为两种:「广度优先遍历 breadth-first traversal」和「深度优先遍历 depth-first traversal」。它们也常被称为「广度优先搜索 breadth-first search」和「深度优先搜索 depth-first search」,简称 BFS 和 DFS 。</p>
|
||||
<h2 id="931">9.3.1 广度优先遍历<a class="headerlink" href="#931" title="Permanent link">¶</a></h2>
|
||||
<p><strong>广度优先遍历是一种由近及远的遍历方式,从某个节点出发,始终优先访问距离最近的顶点,并一层层向外扩张</strong>。如图 9-9 所示,从左上角顶点出发,先遍历该顶点的所有邻接顶点,然后遍历下一个顶点的所有邻接顶点,以此类推,直至所有顶点访问完毕。</p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="图的广度优先遍历" src="../graph_traversal.assets/graph_bfs.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="图的广度优先遍历" class="animation-figure" src="../graph_traversal.assets/graph_bfs.png" /></a></p>
|
||||
<p align="center"> 图 9-9 图的广度优先遍历 </p>
|
||||
|
||||
<h3 id="1">1. 算法实现<a class="headerlink" href="#1" title="Permanent link">¶</a></h3>
|
||||
@ -3823,37 +3823,37 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="2:11"><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" /><div class="tabbed-labels"><label for="__tabbed_2_1"><1></label><label for="__tabbed_2_2"><2></label><label for="__tabbed_2_3"><3></label><label for="__tabbed_2_4"><4></label><label for="__tabbed_2_5"><5></label><label for="__tabbed_2_6"><6></label><label for="__tabbed_2_7"><7></label><label for="__tabbed_2_8"><8></label><label for="__tabbed_2_9"><9></label><label for="__tabbed_2_10"><10></label><label for="__tabbed_2_11"><11></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="图的广度优先遍历步骤" src="../graph_traversal.assets/graph_bfs_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="图的广度优先遍历步骤" class="animation-figure" src="../graph_traversal.assets/graph_bfs_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_bfs_step2" src="../graph_traversal.assets/graph_bfs_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_bfs_step2" class="animation-figure" src="../graph_traversal.assets/graph_bfs_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_bfs_step3" src="../graph_traversal.assets/graph_bfs_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_bfs_step3" class="animation-figure" src="../graph_traversal.assets/graph_bfs_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_bfs_step4" src="../graph_traversal.assets/graph_bfs_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_bfs_step4" class="animation-figure" src="../graph_traversal.assets/graph_bfs_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_bfs_step5" src="../graph_traversal.assets/graph_bfs_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_bfs_step5" class="animation-figure" src="../graph_traversal.assets/graph_bfs_step5.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_bfs_step6" src="../graph_traversal.assets/graph_bfs_step6.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_bfs_step6" class="animation-figure" src="../graph_traversal.assets/graph_bfs_step6.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_bfs_step7" src="../graph_traversal.assets/graph_bfs_step7.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_bfs_step7" class="animation-figure" src="../graph_traversal.assets/graph_bfs_step7.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_bfs_step8" src="../graph_traversal.assets/graph_bfs_step8.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_bfs_step8" class="animation-figure" src="../graph_traversal.assets/graph_bfs_step8.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_bfs_step9" src="../graph_traversal.assets/graph_bfs_step9.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_bfs_step9" class="animation-figure" src="../graph_traversal.assets/graph_bfs_step9.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_bfs_step10" src="../graph_traversal.assets/graph_bfs_step10.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_bfs_step10" class="animation-figure" src="../graph_traversal.assets/graph_bfs_step10.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs_step11.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_bfs_step11" src="../graph_traversal.assets/graph_bfs_step11.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_bfs_step11.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_bfs_step11" class="animation-figure" src="../graph_traversal.assets/graph_bfs_step11.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -3868,7 +3868,7 @@
|
||||
<p><strong>空间复杂度:</strong> 列表 <code>res</code> ,哈希表 <code>visited</code> ,队列 <code>que</code> 中的顶点数量最多为 <span class="arithmatex">\(|V|\)</span> ,使用 <span class="arithmatex">\(O(|V|)\)</span> 空间。</p>
|
||||
<h2 id="932">9.3.2 深度优先遍历<a class="headerlink" href="#932" title="Permanent link">¶</a></h2>
|
||||
<p><strong>深度优先遍历是一种优先走到底、无路可走再回头的遍历方式</strong>。如图 9-11 所示,从左上角顶点出发,访问当前顶点的某个邻接顶点,直到走到尽头时返回,再继续走到尽头并返回,以此类推,直至所有顶点遍历完成。</p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="图的深度优先遍历" src="../graph_traversal.assets/graph_dfs.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="图的深度优先遍历" class="animation-figure" src="../graph_traversal.assets/graph_dfs.png" /></a></p>
|
||||
<p align="center"> 图 9-11 图的深度优先遍历 </p>
|
||||
|
||||
<h3 id="1_1">1. 算法实现<a class="headerlink" href="#1_1" title="Permanent link">¶</a></h3>
|
||||
@ -4206,37 +4206,37 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="4:11"><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" /><div class="tabbed-labels"><label for="__tabbed_4_1"><1></label><label for="__tabbed_4_2"><2></label><label for="__tabbed_4_3"><3></label><label for="__tabbed_4_4"><4></label><label for="__tabbed_4_5"><5></label><label for="__tabbed_4_6"><6></label><label for="__tabbed_4_7"><7></label><label for="__tabbed_4_8"><8></label><label for="__tabbed_4_9"><9></label><label for="__tabbed_4_10"><10></label><label for="__tabbed_4_11"><11></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="图的深度优先遍历步骤" src="../graph_traversal.assets/graph_dfs_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="图的深度优先遍历步骤" class="animation-figure" src="../graph_traversal.assets/graph_dfs_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_dfs_step2" src="../graph_traversal.assets/graph_dfs_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_dfs_step2" class="animation-figure" src="../graph_traversal.assets/graph_dfs_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_dfs_step3" src="../graph_traversal.assets/graph_dfs_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_dfs_step3" class="animation-figure" src="../graph_traversal.assets/graph_dfs_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_dfs_step4" src="../graph_traversal.assets/graph_dfs_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_dfs_step4" class="animation-figure" src="../graph_traversal.assets/graph_dfs_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_dfs_step5" src="../graph_traversal.assets/graph_dfs_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_dfs_step5" class="animation-figure" src="../graph_traversal.assets/graph_dfs_step5.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_dfs_step6" src="../graph_traversal.assets/graph_dfs_step6.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_dfs_step6" class="animation-figure" src="../graph_traversal.assets/graph_dfs_step6.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_dfs_step7" src="../graph_traversal.assets/graph_dfs_step7.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_dfs_step7" class="animation-figure" src="../graph_traversal.assets/graph_dfs_step7.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_dfs_step8" src="../graph_traversal.assets/graph_dfs_step8.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_dfs_step8" class="animation-figure" src="../graph_traversal.assets/graph_dfs_step8.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_dfs_step9" src="../graph_traversal.assets/graph_dfs_step9.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_dfs_step9" class="animation-figure" src="../graph_traversal.assets/graph_dfs_step9.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_dfs_step10" src="../graph_traversal.assets/graph_dfs_step10.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_dfs_step10" class="animation-figure" src="../graph_traversal.assets/graph_dfs_step10.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs_step11.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_dfs_step11" src="../graph_traversal.assets/graph_dfs_step11.png" /></a></p>
|
||||
<p><a class="glightbox" href="../graph_traversal.assets/graph_dfs_step11.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="graph_dfs_step11" class="animation-figure" src="../graph_traversal.assets/graph_dfs_step11.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3292,7 +3292,7 @@
|
||||
<!-- Page content -->
|
||||
<h1 id="9">第 9 章 图<a class="headerlink" href="#9" title="Permanent link">¶</a></h1>
|
||||
<div class="center-table">
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_graph.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="图" src="../assets/covers/chapter_graph.jpg" width="600" /></a></p>
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_graph.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="图" class="cover-image" src="../assets/covers/chapter_graph.jpg" /></a></p>
|
||||
</div>
|
||||
<div class="admonition abstract">
|
||||
<p class="admonition-title">Abstract</p>
|
||||
|
@ -3370,7 +3370,7 @@
|
||||
<p class="admonition-title">Question</p>
|
||||
<p>给定 <span class="arithmatex">\(n\)</span> 个物品,第 <span class="arithmatex">\(i\)</span> 个物品的重量为 <span class="arithmatex">\(wgt[i-1]\)</span>、价值为 <span class="arithmatex">\(val[i-1]\)</span> ,和一个容量为 <span class="arithmatex">\(cap\)</span> 的背包。每个物品只能选择一次,<strong>但可以选择物品的一部分,价值根据选择的重量比例计算</strong>,问在不超过背包容量下背包中物品的最大价值。</p>
|
||||
</div>
|
||||
<p><a class="glightbox" href="../fractional_knapsack_problem.assets/fractional_knapsack_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="分数背包问题的示例数据" src="../fractional_knapsack_problem.assets/fractional_knapsack_example.png" /></a></p>
|
||||
<p><a class="glightbox" href="../fractional_knapsack_problem.assets/fractional_knapsack_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="分数背包问题的示例数据" class="animation-figure" src="../fractional_knapsack_problem.assets/fractional_knapsack_example.png" /></a></p>
|
||||
<p align="center"> 图 15-3 分数背包问题的示例数据 </p>
|
||||
|
||||
<p>分数背包和 0-1 背包整体上非常相似,状态包含当前物品 <span class="arithmatex">\(i\)</span> 和容量 <span class="arithmatex">\(c\)</span> ,目标是求不超过背包容量下的最大价值。</p>
|
||||
@ -3379,7 +3379,7 @@
|
||||
<li>对于物品 <span class="arithmatex">\(i\)</span> ,它在单位重量下的价值为 <span class="arithmatex">\(val[i-1] / wgt[i-1]\)</span> ,简称为单位价值。</li>
|
||||
<li>假设放入一部分物品 <span class="arithmatex">\(i\)</span> ,重量为 <span class="arithmatex">\(w\)</span> ,则背包增加的价值为 <span class="arithmatex">\(w \times val[i-1] / wgt[i-1]\)</span> 。</li>
|
||||
</ol>
|
||||
<p><a class="glightbox" href="../fractional_knapsack_problem.assets/fractional_knapsack_unit_value.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="物品在单位重量下的价值" src="../fractional_knapsack_problem.assets/fractional_knapsack_unit_value.png" /></a></p>
|
||||
<p><a class="glightbox" href="../fractional_knapsack_problem.assets/fractional_knapsack_unit_value.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="物品在单位重量下的价值" class="animation-figure" src="../fractional_knapsack_problem.assets/fractional_knapsack_unit_value.png" /></a></p>
|
||||
<p align="center"> 图 15-4 物品在单位重量下的价值 </p>
|
||||
|
||||
<h3 id="1">1. 贪心策略确定<a class="headerlink" href="#1" title="Permanent link">¶</a></h3>
|
||||
@ -3389,7 +3389,7 @@
|
||||
<li>遍历所有物品,<strong>每轮贪心地选择单位价值最高的物品</strong>。</li>
|
||||
<li>若剩余背包容量不足,则使用当前物品的一部分填满背包即可。</li>
|
||||
</ol>
|
||||
<p><a class="glightbox" href="../fractional_knapsack_problem.assets/fractional_knapsack_greedy_strategy.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="分数背包的贪心策略" src="../fractional_knapsack_problem.assets/fractional_knapsack_greedy_strategy.png" /></a></p>
|
||||
<p><a class="glightbox" href="../fractional_knapsack_problem.assets/fractional_knapsack_greedy_strategy.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="分数背包的贪心策略" class="animation-figure" src="../fractional_knapsack_problem.assets/fractional_knapsack_greedy_strategy.png" /></a></p>
|
||||
<p align="center"> 图 15-5 分数背包的贪心策略 </p>
|
||||
|
||||
<h3 id="2">2. 代码实现<a class="headerlink" href="#2" title="Permanent link">¶</a></h3>
|
||||
@ -3811,7 +3811,7 @@
|
||||
<p>现在从背包中拿出单位重量的任意物品,并替换为单位重量的物品 <span class="arithmatex">\(x\)</span> 。由于物品 <span class="arithmatex">\(x\)</span> 的单位价值最高,因此替换后的总价值一定大于 <code>res</code> 。<strong>这与 <code>res</code> 是最优解矛盾,说明最优解中必须包含物品 <span class="arithmatex">\(x\)</span></strong> 。</p>
|
||||
<p>对于该解中的其他物品,我们也可以构建出上述矛盾。总而言之,<strong>单位价值更大的物品总是更优选择</strong>,这说明贪心策略是有效的。</p>
|
||||
<p>如图 15-6 所示,如果将物品重量和物品单位价值分别看作一个 2D 图表的横轴和纵轴,则分数背包问题可被转化为“求在有限横轴区间下的最大围成面积”。这个类比可以帮助我们从几何角度理解贪心策略的有效性。</p>
|
||||
<p><a class="glightbox" href="../fractional_knapsack_problem.assets/fractional_knapsack_area_chart.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="分数背包问题的几何表示" src="../fractional_knapsack_problem.assets/fractional_knapsack_area_chart.png" /></a></p>
|
||||
<p><a class="glightbox" href="../fractional_knapsack_problem.assets/fractional_knapsack_area_chart.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="分数背包问题的几何表示" class="animation-figure" src="../fractional_knapsack_problem.assets/fractional_knapsack_area_chart.png" /></a></p>
|
||||
<p align="center"> 图 15-6 分数背包问题的几何表示 </p>
|
||||
|
||||
<!-- Source file information -->
|
||||
|
@ -3392,7 +3392,7 @@
|
||||
<p>给定 <span class="arithmatex">\(n\)</span> 种硬币,第 <span class="arithmatex">\(i\)</span> 种硬币的面值为 <span class="arithmatex">\(coins[i - 1]\)</span> ,目标金额为 <span class="arithmatex">\(amt\)</span> ,每种硬币可以重复选取,问能够凑出目标金额的最少硬币个数。如果无法凑出目标金额则返回 <span class="arithmatex">\(-1\)</span> 。</p>
|
||||
</div>
|
||||
<p>本题的贪心策略如图 15-1 所示。给定目标金额,<strong>我们贪心地选择不大于且最接近它的硬币</strong>,不断循环该步骤,直至凑出目标金额为止。</p>
|
||||
<p><a class="glightbox" href="../greedy_algorithm.assets/coin_change_greedy_strategy.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="零钱兑换的贪心策略" src="../greedy_algorithm.assets/coin_change_greedy_strategy.png" /></a></p>
|
||||
<p><a class="glightbox" href="../greedy_algorithm.assets/coin_change_greedy_strategy.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="零钱兑换的贪心策略" class="animation-figure" src="../greedy_algorithm.assets/coin_change_greedy_strategy.png" /></a></p>
|
||||
<p align="center"> 图 15-1 零钱兑换的贪心策略 </p>
|
||||
|
||||
<p>实现代码如下所示。你可能会不由地发出感叹:So Clean !贪心算法仅用十行代码就解决了零钱兑换问题。</p>
|
||||
@ -3648,7 +3648,7 @@
|
||||
<li><strong>反例 <span class="arithmatex">\(coins = [1, 20, 50]\)</span></strong>:假设 <span class="arithmatex">\(amt = 60\)</span> ,贪心算法只能找到 <span class="arithmatex">\(50 + 1 \times 10\)</span> 的兑换组合,共计 <span class="arithmatex">\(11\)</span> 枚硬币,但动态规划可以找到最优解 <span class="arithmatex">\(20 + 20 + 20\)</span> ,仅需 <span class="arithmatex">\(3\)</span> 枚硬币。</li>
|
||||
<li><strong>反例 <span class="arithmatex">\(coins = [1, 49, 50]\)</span></strong>:假设 <span class="arithmatex">\(amt = 98\)</span> ,贪心算法只能找到 <span class="arithmatex">\(50 + 1 \times 48\)</span> 的兑换组合,共计 <span class="arithmatex">\(49\)</span> 枚硬币,但动态规划可以找到最优解 <span class="arithmatex">\(49 + 49\)</span> ,仅需 <span class="arithmatex">\(2\)</span> 枚硬币。</li>
|
||||
</ul>
|
||||
<p><a class="glightbox" href="../greedy_algorithm.assets/coin_change_greedy_vs_dp.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="贪心无法找出最优解的示例" src="../greedy_algorithm.assets/coin_change_greedy_vs_dp.png" /></a></p>
|
||||
<p><a class="glightbox" href="../greedy_algorithm.assets/coin_change_greedy_vs_dp.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="贪心无法找出最优解的示例" class="animation-figure" src="../greedy_algorithm.assets/coin_change_greedy_vs_dp.png" /></a></p>
|
||||
<p align="center"> 图 15-2 贪心无法找出最优解的示例 </p>
|
||||
|
||||
<p>也就是说,对于零钱兑换问题,贪心算法无法保证找到全局最优解,并且有可能找到非常差的解。它更适合用动态规划解决。</p>
|
||||
|
@ -3292,7 +3292,7 @@
|
||||
<!-- Page content -->
|
||||
<h1 id="15">第 15 章 贪心<a class="headerlink" href="#15" title="Permanent link">¶</a></h1>
|
||||
<div class="center-table">
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_greedy.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="贪心" src="../assets/covers/chapter_greedy.jpg" width="600" /></a></p>
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_greedy.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="贪心" class="cover-image" src="../assets/covers/chapter_greedy.jpg" /></a></p>
|
||||
</div>
|
||||
<div class="admonition abstract">
|
||||
<p class="admonition-title">Abstract</p>
|
||||
|
@ -3372,7 +3372,7 @@
|
||||
<p>容器的容量等于高度和宽度的乘积(即面积),其中高度由较短的隔板决定,宽度是两个隔板的数组索引之差。</p>
|
||||
<p>请在数组中选择两个隔板,使得组成的容器的容量最大,返回最大容量。</p>
|
||||
</div>
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="最大容量问题的示例数据" src="../max_capacity_problem.assets/max_capacity_example.png" /></a></p>
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="最大容量问题的示例数据" class="animation-figure" src="../max_capacity_problem.assets/max_capacity_example.png" /></a></p>
|
||||
<p align="center"> 图 15-7 最大容量问题的示例数据 </p>
|
||||
|
||||
<p>容器由任意两个隔板围成,<strong>因此本题的状态为两个隔板的索引,记为 <span class="arithmatex">\([i, j]\)</span></strong> 。</p>
|
||||
@ -3383,16 +3383,16 @@ cap[i, j] = \min(ht[i], ht[j]) \times (j - i)
|
||||
<p>设数组长度为 <span class="arithmatex">\(n\)</span> ,两个隔板的组合数量(即状态总数)为 <span class="arithmatex">\(C_n^2 = \frac{n(n - 1)}{2}\)</span> 个。最直接地,<strong>我们可以穷举所有状态</strong>,从而求得最大容量,时间复杂度为 <span class="arithmatex">\(O(n^2)\)</span> 。</p>
|
||||
<h3 id="1">1. 贪心策略确定<a class="headerlink" href="#1" title="Permanent link">¶</a></h3>
|
||||
<p>这道题还有更高效率的解法。如图 15-8 所示,现选取一个状态 <span class="arithmatex">\([i, j]\)</span> ,其满足索引 <span class="arithmatex">\(i < j\)</span> 且高度 <span class="arithmatex">\(ht[i] < ht[j]\)</span> ,即 <span class="arithmatex">\(i\)</span> 为短板、<span class="arithmatex">\(j\)</span> 为长板。</p>
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_initial_state.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="初始状态" src="../max_capacity_problem.assets/max_capacity_initial_state.png" /></a></p>
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_initial_state.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="初始状态" class="animation-figure" src="../max_capacity_problem.assets/max_capacity_initial_state.png" /></a></p>
|
||||
<p align="center"> 图 15-8 初始状态 </p>
|
||||
|
||||
<p>如图 15-9 所示,<strong>若此时将长板 <span class="arithmatex">\(j\)</span> 向短板 <span class="arithmatex">\(i\)</span> 靠近,则容量一定变小</strong>。</p>
|
||||
<p>这是因为在移动长板 <span class="arithmatex">\(j\)</span> 后,宽度 <span class="arithmatex">\(j-i\)</span> 肯定变小;而高度由短板决定,因此高度只可能不变( <span class="arithmatex">\(i\)</span> 仍为短板)或变小(移动后的 <span class="arithmatex">\(j\)</span> 成为短板)。</p>
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_moving_long_board.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="向内移动长板后的状态" src="../max_capacity_problem.assets/max_capacity_moving_long_board.png" /></a></p>
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_moving_long_board.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="向内移动长板后的状态" class="animation-figure" src="../max_capacity_problem.assets/max_capacity_moving_long_board.png" /></a></p>
|
||||
<p align="center"> 图 15-9 向内移动长板后的状态 </p>
|
||||
|
||||
<p>反向思考,<strong>我们只有向内收缩短板 <span class="arithmatex">\(i\)</span> ,才有可能使容量变大</strong>。因为虽然宽度一定变小,<strong>但高度可能会变大</strong>(移动后的短板 <span class="arithmatex">\(i\)</span> 可能会变长)。例如在图 15-10 中,移动短板后面积变大。</p>
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_moving_short_board.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="向内移动短板后的状态" src="../max_capacity_problem.assets/max_capacity_moving_short_board.png" /></a></p>
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_moving_short_board.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="向内移动短板后的状态" class="animation-figure" src="../max_capacity_problem.assets/max_capacity_moving_short_board.png" /></a></p>
|
||||
<p align="center"> 图 15-10 向内移动短板后的状态 </p>
|
||||
|
||||
<p>由此便可推出本题的贪心策略:初始化两指针分裂容器两端,每轮向内收缩短板对应的指针,直至两指针相遇。</p>
|
||||
@ -3406,31 +3406,31 @@ cap[i, j] = \min(ht[i], ht[j]) \times (j - i)
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="1:9"><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" /><div class="tabbed-labels"><label for="__tabbed_1_1"><1></label><label for="__tabbed_1_2"><2></label><label for="__tabbed_1_3"><3></label><label for="__tabbed_1_4"><4></label><label for="__tabbed_1_5"><5></label><label for="__tabbed_1_6"><6></label><label for="__tabbed_1_7"><7></label><label for="__tabbed_1_8"><8></label><label for="__tabbed_1_9"><9></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_greedy_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="最大容量问题的贪心过程" src="../max_capacity_problem.assets/max_capacity_greedy_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_greedy_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="最大容量问题的贪心过程" class="animation-figure" src="../max_capacity_problem.assets/max_capacity_greedy_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_greedy_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="max_capacity_greedy_step2" src="../max_capacity_problem.assets/max_capacity_greedy_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_greedy_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="max_capacity_greedy_step2" class="animation-figure" src="../max_capacity_problem.assets/max_capacity_greedy_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_greedy_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="max_capacity_greedy_step3" src="../max_capacity_problem.assets/max_capacity_greedy_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_greedy_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="max_capacity_greedy_step3" class="animation-figure" src="../max_capacity_problem.assets/max_capacity_greedy_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_greedy_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="max_capacity_greedy_step4" src="../max_capacity_problem.assets/max_capacity_greedy_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_greedy_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="max_capacity_greedy_step4" class="animation-figure" src="../max_capacity_problem.assets/max_capacity_greedy_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_greedy_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="max_capacity_greedy_step5" src="../max_capacity_problem.assets/max_capacity_greedy_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_greedy_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="max_capacity_greedy_step5" class="animation-figure" src="../max_capacity_problem.assets/max_capacity_greedy_step5.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_greedy_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="max_capacity_greedy_step6" src="../max_capacity_problem.assets/max_capacity_greedy_step6.png" /></a></p>
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_greedy_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="max_capacity_greedy_step6" class="animation-figure" src="../max_capacity_problem.assets/max_capacity_greedy_step6.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_greedy_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="max_capacity_greedy_step7" src="../max_capacity_problem.assets/max_capacity_greedy_step7.png" /></a></p>
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_greedy_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="max_capacity_greedy_step7" class="animation-figure" src="../max_capacity_problem.assets/max_capacity_greedy_step7.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_greedy_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="max_capacity_greedy_step8" src="../max_capacity_problem.assets/max_capacity_greedy_step8.png" /></a></p>
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_greedy_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="max_capacity_greedy_step8" class="animation-figure" src="../max_capacity_problem.assets/max_capacity_greedy_step8.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_greedy_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="max_capacity_greedy_step9" src="../max_capacity_problem.assets/max_capacity_greedy_step9.png" /></a></p>
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_greedy_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="max_capacity_greedy_step9" class="animation-figure" src="../max_capacity_problem.assets/max_capacity_greedy_step9.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -3707,7 +3707,7 @@ cap[i, j] = \min(ht[i], ht[j]) \times (j - i)
|
||||
<div class="arithmatex">\[
|
||||
cap[i, i+1], cap[i, i+2], \dots, cap[i, j-2], cap[i, j-1]
|
||||
\]</div>
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_skipped_states.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="移动短板导致被跳过的状态" src="../max_capacity_problem.assets/max_capacity_skipped_states.png" /></a></p>
|
||||
<p><a class="glightbox" href="../max_capacity_problem.assets/max_capacity_skipped_states.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="移动短板导致被跳过的状态" class="animation-figure" src="../max_capacity_problem.assets/max_capacity_skipped_states.png" /></a></p>
|
||||
<p align="center"> 图 15-12 移动短板导致被跳过的状态 </p>
|
||||
|
||||
<p>观察发现,<strong>这些被跳过的状态实际上就是将长板 <span class="arithmatex">\(j\)</span> 向内移动的所有状态</strong>。而在第二步中,我们已经证明内移长板一定会导致容量变小。也就是说,被跳过的状态都不可能是最优解,<strong>跳过它们不会导致错过最优解</strong>。</p>
|
||||
|
@ -3370,7 +3370,7 @@
|
||||
<p class="admonition-title">Question</p>
|
||||
<p>给定一个正整数 <span class="arithmatex">\(n\)</span> ,将其切分为至少两个正整数的和,求切分后所有整数的乘积最大是多少。</p>
|
||||
</div>
|
||||
<p><a class="glightbox" href="../max_product_cutting_problem.assets/max_product_cutting_definition.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="最大切分乘积的问题定义" src="../max_product_cutting_problem.assets/max_product_cutting_definition.png" /></a></p>
|
||||
<p><a class="glightbox" href="../max_product_cutting_problem.assets/max_product_cutting_definition.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="最大切分乘积的问题定义" class="animation-figure" src="../max_product_cutting_problem.assets/max_product_cutting_definition.png" /></a></p>
|
||||
<p align="center"> 图 15-13 最大切分乘积的问题定义 </p>
|
||||
|
||||
<p>假设我们将 <span class="arithmatex">\(n\)</span> 切分为 <span class="arithmatex">\(m\)</span> 个整数因子,其中第 <span class="arithmatex">\(i\)</span> 个因子记为 <span class="arithmatex">\(n_i\)</span> ,即</p>
|
||||
@ -3393,13 +3393,13 @@ n & \geq 4
|
||||
\]</div>
|
||||
<p>如图 15-14 所示,当 <span class="arithmatex">\(n \geq 4\)</span> 时,切分出一个 <span class="arithmatex">\(2\)</span> 后乘积会变大,<strong>这说明大于等于 <span class="arithmatex">\(4\)</span> 的整数都应该被切分</strong>。</p>
|
||||
<p><strong>贪心策略一</strong>:如果切分方案中包含 <span class="arithmatex">\(\geq 4\)</span> 的因子,那么它就应该被继续切分。最终的切分方案只应出现 <span class="arithmatex">\(1\)</span>、<span class="arithmatex">\(2\)</span>、<span class="arithmatex">\(3\)</span> 这三种因子。</p>
|
||||
<p><a class="glightbox" href="../max_product_cutting_problem.assets/max_product_cutting_greedy_infer1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="切分导致乘积变大" src="../max_product_cutting_problem.assets/max_product_cutting_greedy_infer1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../max_product_cutting_problem.assets/max_product_cutting_greedy_infer1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="切分导致乘积变大" class="animation-figure" src="../max_product_cutting_problem.assets/max_product_cutting_greedy_infer1.png" /></a></p>
|
||||
<p align="center"> 图 15-14 切分导致乘积变大 </p>
|
||||
|
||||
<p>接下来思考哪个因子是最优的。在 <span class="arithmatex">\(1\)</span>、<span class="arithmatex">\(2\)</span>、<span class="arithmatex">\(3\)</span> 这三个因子中,显然 <span class="arithmatex">\(1\)</span> 是最差的,因为 <span class="arithmatex">\(1 \times (n-1) < n\)</span> 恒成立,即切分出 <span class="arithmatex">\(1\)</span> 反而会导致乘积减小。</p>
|
||||
<p>如图 15-15 所示,当 <span class="arithmatex">\(n = 6\)</span> 时,有 <span class="arithmatex">\(3 \times 3 > 2 \times 2 \times 2\)</span> 。<strong>这意味着切分出 <span class="arithmatex">\(3\)</span> 比切分出 <span class="arithmatex">\(2\)</span> 更优</strong>。</p>
|
||||
<p><strong>贪心策略二</strong>:在切分方案中,最多只应存在两个 <span class="arithmatex">\(2\)</span> 。因为三个 <span class="arithmatex">\(2\)</span> 总是可以被替换为两个 <span class="arithmatex">\(3\)</span> ,从而获得更大乘积。</p>
|
||||
<p><a class="glightbox" href="../max_product_cutting_problem.assets/max_product_cutting_greedy_infer2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="最优切分因子" src="../max_product_cutting_problem.assets/max_product_cutting_greedy_infer2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../max_product_cutting_problem.assets/max_product_cutting_greedy_infer2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="最优切分因子" class="animation-figure" src="../max_product_cutting_problem.assets/max_product_cutting_greedy_infer2.png" /></a></p>
|
||||
<p align="center"> 图 15-15 最优切分因子 </p>
|
||||
|
||||
<p>总结以上,可推出以下贪心策略。</p>
|
||||
@ -3671,7 +3671,7 @@ n = 3 a + b
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p><a class="glightbox" href="../max_product_cutting_problem.assets/max_product_cutting_greedy_calculation.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="最大切分乘积的计算方法" src="../max_product_cutting_problem.assets/max_product_cutting_greedy_calculation.png" /></a></p>
|
||||
<p><a class="glightbox" href="../max_product_cutting_problem.assets/max_product_cutting_greedy_calculation.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="最大切分乘积的计算方法" class="animation-figure" src="../max_product_cutting_problem.assets/max_product_cutting_greedy_calculation.png" /></a></p>
|
||||
<p align="center"> 图 15-16 最大切分乘积的计算方法 </p>
|
||||
|
||||
<p><strong>时间复杂度取决于编程语言的幂运算的实现方法</strong>。以 Python 为例,常用的幂计算函数有三种。</p>
|
||||
|
@ -3382,7 +3382,7 @@
|
||||
<h1 id="63">6.3 哈希算法<a class="headerlink" href="#63" title="Permanent link">¶</a></h1>
|
||||
<p>在上两节中,我们了解了哈希表的工作原理和哈希冲突的处理方法。然而无论是开放寻址还是链地址法,<strong>它们只能保证哈希表可以在发生冲突时正常工作,但无法减少哈希冲突的发生</strong>。</p>
|
||||
<p>如果哈希冲突过于频繁,哈希表的性能则会急剧劣化。如图 6-8 所示,对于链地址哈希表,理想情况下键值对平均分布在各个桶中,达到最佳查询效率;最差情况下所有键值对都被存储到同一个桶中,时间复杂度退化至 <span class="arithmatex">\(O(n)\)</span> 。</p>
|
||||
<p><a class="glightbox" href="../hash_algorithm.assets/hash_collision_best_worst_condition.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="哈希冲突的最佳与最差情况" src="../hash_algorithm.assets/hash_collision_best_worst_condition.png" /></a></p>
|
||||
<p><a class="glightbox" href="../hash_algorithm.assets/hash_collision_best_worst_condition.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="哈希冲突的最佳与最差情况" class="animation-figure" src="../hash_algorithm.assets/hash_collision_best_worst_condition.png" /></a></p>
|
||||
<p align="center"> 图 6-8 哈希冲突的最佳与最差情况 </p>
|
||||
|
||||
<p><strong>键值对的分布情况由哈希函数决定</strong>。回忆哈希函数的计算步骤,先计算哈希值,再对数组长度取模:</p>
|
||||
|
@ -3429,7 +3429,7 @@
|
||||
<p>哈希表的结构改良方法主要包括“链式地址”和“开放寻址”。</p>
|
||||
<h2 id="621">6.2.1 链式地址<a class="headerlink" href="#621" title="Permanent link">¶</a></h2>
|
||||
<p>在原始哈希表中,每个桶仅能存储一个键值对。「链式地址 separate chaining」将单个元素转换为链表,将键值对作为链表节点,将所有发生冲突的键值对都存储在同一链表中。图 6-5 展示了一个链式地址哈希表的例子。</p>
|
||||
<p><a class="glightbox" href="../hash_collision.assets/hash_table_chaining.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="链式地址哈希表" src="../hash_collision.assets/hash_table_chaining.png" /></a></p>
|
||||
<p><a class="glightbox" href="../hash_collision.assets/hash_table_chaining.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="链式地址哈希表" class="animation-figure" src="../hash_collision.assets/hash_table_chaining.png" /></a></p>
|
||||
<p align="center"> 图 6-5 链式地址哈希表 </p>
|
||||
|
||||
<p>基于链式地址实现的哈希表的操作方法发生了以下变化。</p>
|
||||
@ -4718,12 +4718,12 @@
|
||||
<li><strong>查找元素</strong>:若发现哈希冲突,则使用相同步长向后线性遍历,直到找到对应元素,返回 <code>value</code> 即可;如果遇到空桶,说明目标元素不在哈希表中,返回 <span class="arithmatex">\(\text{None}\)</span> 。</li>
|
||||
</ul>
|
||||
<p>图 6-6 展示了开放寻址(线性探测)哈希表的键值对分布。根据此哈希函数,最后两位相同的 <code>key</code> 都会被映射到相同的桶。而通过线性探测,它们被依次存储在该桶以及之下的桶中。</p>
|
||||
<p><a class="glightbox" href="../hash_collision.assets/hash_table_linear_probing.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="开放寻址和线性探测" src="../hash_collision.assets/hash_table_linear_probing.png" /></a></p>
|
||||
<p><a class="glightbox" href="../hash_collision.assets/hash_table_linear_probing.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="开放寻址和线性探测" class="animation-figure" src="../hash_collision.assets/hash_table_linear_probing.png" /></a></p>
|
||||
<p align="center"> 图 6-6 开放寻址和线性探测 </p>
|
||||
|
||||
<p>然而,<strong>线性探测容易产生“聚集现象”</strong>。具体来说,数组中连续被占用的位置越长,这些连续位置发生哈希冲突的可能性越大,从而进一步促使该位置的聚堆生长,形成恶性循环,最终导致增删查改操作效率劣化。</p>
|
||||
<p>值得注意的是,<strong>我们不能在开放寻址哈希表中直接删除元素</strong>。这是因为删除元素会在数组内产生一个空桶 <span class="arithmatex">\(\text{None}\)</span> ,而当查询元素时,线性探测到该空桶就会返回,因此在该空桶之下的元素都无法再被访问到,程序可能误判这些元素不存在。</p>
|
||||
<p><a class="glightbox" href="../hash_collision.assets/hash_table_open_addressing_deletion.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="在开放寻址中删除元素导致的查询问题" src="../hash_collision.assets/hash_table_open_addressing_deletion.png" /></a></p>
|
||||
<p><a class="glightbox" href="../hash_collision.assets/hash_table_open_addressing_deletion.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="在开放寻址中删除元素导致的查询问题" class="animation-figure" src="../hash_collision.assets/hash_table_open_addressing_deletion.png" /></a></p>
|
||||
<p align="center"> 图 6-7 在开放寻址中删除元素导致的查询问题 </p>
|
||||
|
||||
<p>为了解决该问题,我们可以采用「懒删除 lazy deletion」机制:它不直接从哈希表中移除元素,<strong>而是利用一个常量 <code>TOMBSTONE</code> 来标记这个桶</strong>。在该机制下,<span class="arithmatex">\(\text{None}\)</span> 和 <code>TOMBSTONE</code> 都代表空桶,都可以放置键值对。但不同的是,线性探测到 <code>TOMBSTONE</code> 时应该继续遍历,因为其之下可能还存在键值对。</p>
|
||||
|
@ -3368,7 +3368,7 @@
|
||||
<h1 id="61">6.1 哈希表<a class="headerlink" href="#61" title="Permanent link">¶</a></h1>
|
||||
<p>「哈希表 hash table」,又称「散列表」,其通过建立键 <code>key</code> 与值 <code>value</code> 之间的映射,实现高效的元素查询。具体而言,我们向哈希表输入一个键 <code>key</code> ,则可以在 <span class="arithmatex">\(O(1)\)</span> 时间内获取对应的值 <code>value</code> 。</p>
|
||||
<p>如图 6-1 所示,给定 <span class="arithmatex">\(n\)</span> 个学生,每个学生都有“姓名”和“学号”两项数据。假如我们希望实现“输入一个学号,返回对应的姓名”的查询功能,则可以采用图 6-1 所示的哈希表来实现。</p>
|
||||
<p><a class="glightbox" href="../hash_map.assets/hash_table_lookup.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="哈希表的抽象表示" src="../hash_map.assets/hash_table_lookup.png" /></a></p>
|
||||
<p><a class="glightbox" href="../hash_map.assets/hash_table_lookup.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="哈希表的抽象表示" class="animation-figure" src="../hash_map.assets/hash_table_lookup.png" /></a></p>
|
||||
<p align="center"> 图 6-1 哈希表的抽象表示 </p>
|
||||
|
||||
<p>除哈希表外,数组和链表也可以实现查询功能,它们的效率对比如表 6-1 所示。</p>
|
||||
@ -3823,7 +3823,7 @@
|
||||
</code></pre></div>
|
||||
<p>随后,我们就可以利用 <code>index</code> 在哈希表中访问对应的桶,从而获取 <code>value</code> 。</p>
|
||||
<p>设数组长度 <code>capacity = 100</code>、哈希算法 <code>hash(key) = key</code> ,易得哈希函数为 <code>key % 100</code> 。图 6-2 以 <code>key</code> 学号和 <code>value</code> 姓名为例,展示了哈希函数的工作原理。</p>
|
||||
<p><a class="glightbox" href="../hash_map.assets/hash_function.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="哈希函数工作原理" src="../hash_map.assets/hash_function.png" /></a></p>
|
||||
<p><a class="glightbox" href="../hash_map.assets/hash_function.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="哈希函数工作原理" class="animation-figure" src="../hash_map.assets/hash_function.png" /></a></p>
|
||||
<p align="center"> 图 6-2 哈希函数工作原理 </p>
|
||||
|
||||
<p>以下代码实现了一个简单哈希表。其中,我们将 <code>key</code> 和 <code>value</code> 封装成一个类 <code>Pair</code> ,以表示键值对。</p>
|
||||
@ -4952,12 +4952,12 @@
|
||||
<a id="__codelineno-37-2" name="__codelineno-37-2" href="#__codelineno-37-2"></a><span class="m">20336</span><span class="w"> </span>%<span class="w"> </span><span class="nv">100</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">36</span>
|
||||
</code></pre></div>
|
||||
<p>如图 6-3 所示,两个学号指向了同一个姓名,这显然是不对的。我们将这种多个输入对应同一输出的情况称为「哈希冲突 hash collision」。</p>
|
||||
<p><a class="glightbox" href="../hash_map.assets/hash_collision.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="哈希冲突示例" src="../hash_map.assets/hash_collision.png" /></a></p>
|
||||
<p><a class="glightbox" href="../hash_map.assets/hash_collision.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="哈希冲突示例" class="animation-figure" src="../hash_map.assets/hash_collision.png" /></a></p>
|
||||
<p align="center"> 图 6-3 哈希冲突示例 </p>
|
||||
|
||||
<p>容易想到,哈希表容量 <span class="arithmatex">\(n\)</span> 越大,多个 <code>key</code> 被分配到同一个桶中的概率就越低,冲突就越少。因此,<strong>我们可以通过扩容哈希表来减少哈希冲突</strong>。</p>
|
||||
<p>如图 6-4 所示,扩容前键值对 <code>(136, A)</code> 和 <code>(236, D)</code> 发生冲突,扩容后冲突消失。</p>
|
||||
<p><a class="glightbox" href="../hash_map.assets/hash_table_reshash.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="哈希表扩容" src="../hash_map.assets/hash_table_reshash.png" /></a></p>
|
||||
<p><a class="glightbox" href="../hash_map.assets/hash_table_reshash.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="哈希表扩容" class="animation-figure" src="../hash_map.assets/hash_table_reshash.png" /></a></p>
|
||||
<p align="center"> 图 6-4 哈希表扩容 </p>
|
||||
|
||||
<p>类似于数组扩容,哈希表扩容需将所有键值对从原哈希表迁移至新哈希表,非常耗时。并且由于哈希表容量 <code>capacity</code> 改变,我们需要通过哈希函数来重新计算所有键值对的存储位置,这进一步提高了扩容过程的计算开销。为此,编程语言通常会预留足够大的哈希表容量,防止频繁扩容。</p>
|
||||
|
@ -3292,7 +3292,7 @@
|
||||
<!-- Page content -->
|
||||
<h1 id="6">第 6 章 哈希表<a class="headerlink" href="#6" title="Permanent link">¶</a></h1>
|
||||
<div class="center-table">
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_hashing.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="哈希表" src="../assets/covers/chapter_hashing.jpg" width="600" /></a></p>
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_hashing.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="哈希表" class="cover-image" src="../assets/covers/chapter_hashing.jpg" /></a></p>
|
||||
</div>
|
||||
<div class="admonition abstract">
|
||||
<p class="admonition-title">Abstract</p>
|
||||
|
@ -3543,7 +3543,7 @@
|
||||
</ul>
|
||||
<p>将上述两者相乘,可得到建堆过程的时间复杂度为 <span class="arithmatex">\(O(n \log n)\)</span> 。<strong>但这个估算结果并不准确,因为我们没有考虑到二叉树底层节点数量远多于顶层节点的性质</strong>。</p>
|
||||
<p>接下来我们来进行更为准确的计算。为了减小计算难度,假设给定一个节点数量为 <span class="arithmatex">\(n\)</span> ,高度为 <span class="arithmatex">\(h\)</span> 的“完美二叉树”,该假设不会影响计算结果的正确性。</p>
|
||||
<p><a class="glightbox" href="../build_heap.assets/heapify_operations_count.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="完美二叉树的各层节点数量" src="../build_heap.assets/heapify_operations_count.png" /></a></p>
|
||||
<p><a class="glightbox" href="../build_heap.assets/heapify_operations_count.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="完美二叉树的各层节点数量" class="animation-figure" src="../build_heap.assets/heapify_operations_count.png" /></a></p>
|
||||
<p align="center"> 图 8-5 完美二叉树的各层节点数量 </p>
|
||||
|
||||
<p>如图 8-5 所示,节点“从顶至底堆化”的最大迭代次数等于该节点到叶节点的距离,而该距离正是“节点高度”。因此,我们可以将各层的“节点数量 <span class="arithmatex">\(\times\)</span> 节点高度”求和,<strong>从而得到所有节点的堆化迭代次数的总和</strong>。</p>
|
||||
|
@ -3439,7 +3439,7 @@
|
||||
<li>「大顶堆 max heap」:任意节点的值 <span class="arithmatex">\(\geq\)</span> 其子节点的值。</li>
|
||||
<li>「小顶堆 min heap」:任意节点的值 <span class="arithmatex">\(\leq\)</span> 其子节点的值。</li>
|
||||
</ul>
|
||||
<p><a class="glightbox" href="../heap.assets/min_heap_and_max_heap.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="小顶堆与大顶堆" src="../heap.assets/min_heap_and_max_heap.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap.assets/min_heap_and_max_heap.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="小顶堆与大顶堆" class="animation-figure" src="../heap.assets/min_heap_and_max_heap.png" /></a></p>
|
||||
<p align="center"> 图 8-1 小顶堆与大顶堆 </p>
|
||||
|
||||
<p>堆作为完全二叉树的一个特例,具有以下特性。</p>
|
||||
@ -3791,7 +3791,7 @@
|
||||
<p>我们在二叉树章节中学习到,完全二叉树非常适合用数组来表示。由于堆正是一种完全二叉树,<strong>我们将采用数组来存储堆</strong>。</p>
|
||||
<p>当使用数组表示二叉树时,元素代表节点值,索引代表节点在二叉树中的位置。<strong>节点指针通过索引映射公式来实现</strong>。</p>
|
||||
<p>如图 8-2 所示,给定索引 <span class="arithmatex">\(i\)</span> ,其左子节点索引为 <span class="arithmatex">\(2i + 1\)</span> ,右子节点索引为 <span class="arithmatex">\(2i + 2\)</span> ,父节点索引为 <span class="arithmatex">\((i - 1) / 2\)</span>(向下取整)。当索引越界时,表示空节点或节点不存在。</p>
|
||||
<p><a class="glightbox" href="../heap.assets/representation_of_heap.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="堆的表示与存储" src="../heap.assets/representation_of_heap.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap.assets/representation_of_heap.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="堆的表示与存储" class="animation-figure" src="../heap.assets/representation_of_heap.png" /></a></p>
|
||||
<p align="center"> 图 8-2 堆的表示与存储 </p>
|
||||
|
||||
<p>我们可以将索引映射公式封装成函数,方便后续使用。</p>
|
||||
@ -4097,31 +4097,31 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="4:9"><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" /><div class="tabbed-labels"><label for="__tabbed_4_1"><1></label><label for="__tabbed_4_2"><2></label><label for="__tabbed_4_3"><3></label><label for="__tabbed_4_4"><4></label><label for="__tabbed_4_5"><5></label><label for="__tabbed_4_6"><6></label><label for="__tabbed_4_7"><7></label><label for="__tabbed_4_8"><8></label><label for="__tabbed_4_9"><9></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap.assets/heap_push_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="元素入堆步骤" src="../heap.assets/heap_push_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap.assets/heap_push_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="元素入堆步骤" class="animation-figure" src="../heap.assets/heap_push_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap.assets/heap_push_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_push_step2" src="../heap.assets/heap_push_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap.assets/heap_push_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_push_step2" class="animation-figure" src="../heap.assets/heap_push_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap.assets/heap_push_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_push_step3" src="../heap.assets/heap_push_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap.assets/heap_push_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_push_step3" class="animation-figure" src="../heap.assets/heap_push_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap.assets/heap_push_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_push_step4" src="../heap.assets/heap_push_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap.assets/heap_push_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_push_step4" class="animation-figure" src="../heap.assets/heap_push_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap.assets/heap_push_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_push_step5" src="../heap.assets/heap_push_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap.assets/heap_push_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_push_step5" class="animation-figure" src="../heap.assets/heap_push_step5.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap.assets/heap_push_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_push_step6" src="../heap.assets/heap_push_step6.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap.assets/heap_push_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_push_step6" class="animation-figure" src="../heap.assets/heap_push_step6.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap.assets/heap_push_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_push_step7" src="../heap.assets/heap_push_step7.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap.assets/heap_push_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_push_step7" class="animation-figure" src="../heap.assets/heap_push_step7.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap.assets/heap_push_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_push_step8" src="../heap.assets/heap_push_step8.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap.assets/heap_push_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_push_step8" class="animation-figure" src="../heap.assets/heap_push_step8.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap.assets/heap_push_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_push_step9" src="../heap.assets/heap_push_step9.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap.assets/heap_push_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_push_step9" class="animation-figure" src="../heap.assets/heap_push_step9.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -4455,34 +4455,34 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="6:10"><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" /><div class="tabbed-labels"><label for="__tabbed_6_1"><1></label><label for="__tabbed_6_2"><2></label><label for="__tabbed_6_3"><3></label><label for="__tabbed_6_4"><4></label><label for="__tabbed_6_5"><5></label><label for="__tabbed_6_6"><6></label><label for="__tabbed_6_7"><7></label><label for="__tabbed_6_8"><8></label><label for="__tabbed_6_9"><9></label><label for="__tabbed_6_10"><10></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap.assets/heap_pop_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="堆顶元素出堆步骤" src="../heap.assets/heap_pop_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap.assets/heap_pop_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="堆顶元素出堆步骤" class="animation-figure" src="../heap.assets/heap_pop_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap.assets/heap_pop_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_pop_step2" src="../heap.assets/heap_pop_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap.assets/heap_pop_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_pop_step2" class="animation-figure" src="../heap.assets/heap_pop_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap.assets/heap_pop_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_pop_step3" src="../heap.assets/heap_pop_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap.assets/heap_pop_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_pop_step3" class="animation-figure" src="../heap.assets/heap_pop_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap.assets/heap_pop_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_pop_step4" src="../heap.assets/heap_pop_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap.assets/heap_pop_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_pop_step4" class="animation-figure" src="../heap.assets/heap_pop_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap.assets/heap_pop_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_pop_step5" src="../heap.assets/heap_pop_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap.assets/heap_pop_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_pop_step5" class="animation-figure" src="../heap.assets/heap_pop_step5.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap.assets/heap_pop_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_pop_step6" src="../heap.assets/heap_pop_step6.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap.assets/heap_pop_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_pop_step6" class="animation-figure" src="../heap.assets/heap_pop_step6.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap.assets/heap_pop_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_pop_step7" src="../heap.assets/heap_pop_step7.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap.assets/heap_pop_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_pop_step7" class="animation-figure" src="../heap.assets/heap_pop_step7.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap.assets/heap_pop_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_pop_step8" src="../heap.assets/heap_pop_step8.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap.assets/heap_pop_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_pop_step8" class="animation-figure" src="../heap.assets/heap_pop_step8.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap.assets/heap_pop_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_pop_step9" src="../heap.assets/heap_pop_step9.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap.assets/heap_pop_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_pop_step9" class="animation-figure" src="../heap.assets/heap_pop_step9.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap.assets/heap_pop_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_pop_step10" src="../heap.assets/heap_pop_step10.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap.assets/heap_pop_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_pop_step10" class="animation-figure" src="../heap.assets/heap_pop_step10.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3292,7 +3292,7 @@
|
||||
<!-- Page content -->
|
||||
<h1 id="8">第 8 章 堆<a class="headerlink" href="#8" title="Permanent link">¶</a></h1>
|
||||
<div class="center-table">
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_heap.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="堆" src="../assets/covers/chapter_heap.jpg" width="600" /></a></p>
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_heap.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="堆" class="cover-image" src="../assets/covers/chapter_heap.jpg" /></a></p>
|
||||
</div>
|
||||
<div class="admonition abstract">
|
||||
<p class="admonition-title">Abstract</p>
|
||||
|
@ -3374,7 +3374,7 @@
|
||||
<h2 id="831">8.3.1 方法一:遍历选择<a class="headerlink" href="#831" title="Permanent link">¶</a></h2>
|
||||
<p>我们可以进行图 8-6 所示的 <span class="arithmatex">\(k\)</span> 轮遍历,分别在每轮中提取第 <span class="arithmatex">\(1\)</span>、<span class="arithmatex">\(2\)</span>、<span class="arithmatex">\(\dots\)</span>、<span class="arithmatex">\(k\)</span> 大的元素,时间复杂度为 <span class="arithmatex">\(O(nk)\)</span> 。</p>
|
||||
<p>此方法只适用于 <span class="arithmatex">\(k \ll n\)</span> 的情况,因为当 <span class="arithmatex">\(k\)</span> 与 <span class="arithmatex">\(n\)</span> 比较接近时,其时间复杂度趋向于 <span class="arithmatex">\(O(n^2)\)</span> ,非常耗时。</p>
|
||||
<p><a class="glightbox" href="../top_k.assets/top_k_traversal.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="遍历寻找最大的 k 个元素" src="../top_k.assets/top_k_traversal.png" /></a></p>
|
||||
<p><a class="glightbox" href="../top_k.assets/top_k_traversal.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="遍历寻找最大的 k 个元素" class="animation-figure" src="../top_k.assets/top_k_traversal.png" /></a></p>
|
||||
<p align="center"> 图 8-6 遍历寻找最大的 k 个元素 </p>
|
||||
|
||||
<div class="admonition tip">
|
||||
@ -3384,7 +3384,7 @@
|
||||
<h2 id="832">8.3.2 方法二:排序<a class="headerlink" href="#832" title="Permanent link">¶</a></h2>
|
||||
<p>如图 8-7 所示,我们可以先对数组 <code>nums</code> 进行排序,再返回最右边的 <span class="arithmatex">\(k\)</span> 个元素,时间复杂度为 <span class="arithmatex">\(O(n \log n)\)</span> 。</p>
|
||||
<p>显然,该方法“超额”完成任务了,因为我们只需要找出最大的 <span class="arithmatex">\(k\)</span> 个元素即可,而不需要排序其他元素。</p>
|
||||
<p><a class="glightbox" href="../top_k.assets/top_k_sorting.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="排序寻找最大的 k 个元素" src="../top_k.assets/top_k_sorting.png" /></a></p>
|
||||
<p><a class="glightbox" href="../top_k.assets/top_k_sorting.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="排序寻找最大的 k 个元素" class="animation-figure" src="../top_k.assets/top_k_sorting.png" /></a></p>
|
||||
<p align="center"> 图 8-7 排序寻找最大的 k 个元素 </p>
|
||||
|
||||
<h2 id="833">8.3.3 方法三:堆<a class="headerlink" href="#833" title="Permanent link">¶</a></h2>
|
||||
@ -3398,31 +3398,31 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="1:9"><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" /><div class="tabbed-labels"><label for="__tabbed_1_1"><1></label><label for="__tabbed_1_2"><2></label><label for="__tabbed_1_3"><3></label><label for="__tabbed_1_4"><4></label><label for="__tabbed_1_5"><5></label><label for="__tabbed_1_6"><6></label><label for="__tabbed_1_7"><7></label><label for="__tabbed_1_8"><8></label><label for="__tabbed_1_9"><9></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../top_k.assets/top_k_heap_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="基于堆寻找最大的 k 个元素" src="../top_k.assets/top_k_heap_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../top_k.assets/top_k_heap_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="基于堆寻找最大的 k 个元素" class="animation-figure" src="../top_k.assets/top_k_heap_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../top_k.assets/top_k_heap_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="top_k_heap_step2" src="../top_k.assets/top_k_heap_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../top_k.assets/top_k_heap_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="top_k_heap_step2" class="animation-figure" src="../top_k.assets/top_k_heap_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../top_k.assets/top_k_heap_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="top_k_heap_step3" src="../top_k.assets/top_k_heap_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../top_k.assets/top_k_heap_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="top_k_heap_step3" class="animation-figure" src="../top_k.assets/top_k_heap_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../top_k.assets/top_k_heap_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="top_k_heap_step4" src="../top_k.assets/top_k_heap_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../top_k.assets/top_k_heap_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="top_k_heap_step4" class="animation-figure" src="../top_k.assets/top_k_heap_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../top_k.assets/top_k_heap_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="top_k_heap_step5" src="../top_k.assets/top_k_heap_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../top_k.assets/top_k_heap_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="top_k_heap_step5" class="animation-figure" src="../top_k.assets/top_k_heap_step5.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../top_k.assets/top_k_heap_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="top_k_heap_step6" src="../top_k.assets/top_k_heap_step6.png" /></a></p>
|
||||
<p><a class="glightbox" href="../top_k.assets/top_k_heap_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="top_k_heap_step6" class="animation-figure" src="../top_k.assets/top_k_heap_step6.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../top_k.assets/top_k_heap_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="top_k_heap_step7" src="../top_k.assets/top_k_heap_step7.png" /></a></p>
|
||||
<p><a class="glightbox" href="../top_k.assets/top_k_heap_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="top_k_heap_step7" class="animation-figure" src="../top_k.assets/top_k_heap_step7.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../top_k.assets/top_k_heap_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="top_k_heap_step8" src="../top_k.assets/top_k_heap_step8.png" /></a></p>
|
||||
<p><a class="glightbox" href="../top_k.assets/top_k_heap_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="top_k_heap_step8" class="animation-figure" src="../top_k.assets/top_k_heap_step8.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../top_k.assets/top_k_heap_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="top_k_heap_step9" src="../top_k.assets/top_k_heap_step9.png" /></a></p>
|
||||
<p><a class="glightbox" href="../top_k.assets/top_k_heap_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="top_k_heap_step9" class="animation-figure" src="../top_k.assets/top_k_heap_step9.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3297,19 +3297,19 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="1:5"><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" /><div class="tabbed-labels"><label for="__tabbed_1_1"><1></label><label for="__tabbed_1_2"><2></label><label for="__tabbed_1_3"><3></label><label for="__tabbed_1_4"><4></label><label for="__tabbed_1_5"><5></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../algorithms_are_everywhere.assets/binary_search_dictionary_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="查字典步骤" src="../algorithms_are_everywhere.assets/binary_search_dictionary_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../algorithms_are_everywhere.assets/binary_search_dictionary_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="查字典步骤" class="animation-figure" src="../algorithms_are_everywhere.assets/binary_search_dictionary_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../algorithms_are_everywhere.assets/binary_search_dictionary_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_dictionary_step2" src="../algorithms_are_everywhere.assets/binary_search_dictionary_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../algorithms_are_everywhere.assets/binary_search_dictionary_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_dictionary_step2" class="animation-figure" src="../algorithms_are_everywhere.assets/binary_search_dictionary_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../algorithms_are_everywhere.assets/binary_search_dictionary_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_dictionary_step3" src="../algorithms_are_everywhere.assets/binary_search_dictionary_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../algorithms_are_everywhere.assets/binary_search_dictionary_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_dictionary_step3" class="animation-figure" src="../algorithms_are_everywhere.assets/binary_search_dictionary_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../algorithms_are_everywhere.assets/binary_search_dictionary_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_dictionary_step4" src="../algorithms_are_everywhere.assets/binary_search_dictionary_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../algorithms_are_everywhere.assets/binary_search_dictionary_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_dictionary_step4" class="animation-figure" src="../algorithms_are_everywhere.assets/binary_search_dictionary_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../algorithms_are_everywhere.assets/binary_search_dictionary_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_dictionary_step5" src="../algorithms_are_everywhere.assets/binary_search_dictionary_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../algorithms_are_everywhere.assets/binary_search_dictionary_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_dictionary_step5" class="animation-figure" src="../algorithms_are_everywhere.assets/binary_search_dictionary_step5.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -3322,7 +3322,7 @@
|
||||
<li>在无序部分抽出一张扑克牌,插入至有序部分的正确位置;完成后最左 2 张扑克已经有序。</li>
|
||||
<li>不断循环步骤 <code>2.</code> ,每一轮将一张扑克牌从无序部分插入至有序部分,直至所有扑克牌都有序。</li>
|
||||
</ol>
|
||||
<p><a class="glightbox" href="../algorithms_are_everywhere.assets/playing_cards_sorting.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="扑克排序步骤" src="../algorithms_are_everywhere.assets/playing_cards_sorting.png" /></a></p>
|
||||
<p><a class="glightbox" href="../algorithms_are_everywhere.assets/playing_cards_sorting.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="扑克排序步骤" class="animation-figure" src="../algorithms_are_everywhere.assets/playing_cards_sorting.png" /></a></p>
|
||||
<p align="center"> 图 1-2 扑克排序步骤 </p>
|
||||
|
||||
<p>上述整理扑克牌的方法本质上是“插入排序”算法,它在处理小型数据集时非常高效。许多编程语言的排序库函数中都存在插入排序的身影。</p>
|
||||
@ -3334,7 +3334,7 @@
|
||||
<li>从剩余可选项中拿出最大的 <span class="arithmatex">\(1\)</span> 元,剩余 <span class="arithmatex">\(1 - 1 = 0\)</span> 元。</li>
|
||||
<li>完成找零,方案为 <span class="arithmatex">\(20 + 10 + 1 = 31\)</span> 元。</li>
|
||||
</ol>
|
||||
<p><a class="glightbox" href="../algorithms_are_everywhere.assets/greedy_change.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="货币找零过程" src="../algorithms_are_everywhere.assets/greedy_change.png" /></a></p>
|
||||
<p><a class="glightbox" href="../algorithms_are_everywhere.assets/greedy_change.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="货币找零过程" class="animation-figure" src="../algorithms_are_everywhere.assets/greedy_change.png" /></a></p>
|
||||
<p align="center"> 图 1-3 货币找零过程 </p>
|
||||
|
||||
<p>在以上步骤中,我们每一步都采取当前看来最好的选择(尽可能用大面额的货币),最终得到了可行的找零方案。从数据结构与算法的角度看,这种方法本质上是“贪心”算法。</p>
|
||||
|
@ -3292,7 +3292,7 @@
|
||||
<!-- Page content -->
|
||||
<h1 id="1">第 1 章 初识算法<a class="headerlink" href="#1" title="Permanent link">¶</a></h1>
|
||||
<div class="center-table">
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_introduction.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="初识算法" src="../assets/covers/chapter_introduction.jpg" width="600" /></a></p>
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_introduction.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="初识算法" class="cover-image" src="../assets/covers/chapter_introduction.jpg" /></a></p>
|
||||
</div>
|
||||
<div class="admonition abstract">
|
||||
<p class="admonition-title">Abstract</p>
|
||||
|
@ -3392,11 +3392,11 @@
|
||||
<li>算法是数据结构发挥作用的舞台。数据结构本身仅存储数据信息,结合算法才能解决特定问题。</li>
|
||||
<li>算法通常可以基于不同的数据结构进行实现,但执行效率可能相差很大,选择合适的数据结构是关键。</li>
|
||||
</ul>
|
||||
<p><a class="glightbox" href="../what_is_dsa.assets/relationship_between_data_structure_and_algorithm.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="数据结构与算法的关系" src="../what_is_dsa.assets/relationship_between_data_structure_and_algorithm.png" /></a></p>
|
||||
<p><a class="glightbox" href="../what_is_dsa.assets/relationship_between_data_structure_and_algorithm.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="数据结构与算法的关系" class="animation-figure" src="../what_is_dsa.assets/relationship_between_data_structure_and_algorithm.png" /></a></p>
|
||||
<p align="center"> 图 1-4 数据结构与算法的关系 </p>
|
||||
|
||||
<p>数据结构与算法犹如图 1-5 所示的拼装积木。一套积木,除了包含许多零件之外,还附有详细的组装说明书。我们按照说明书一步步操作,就能组装出精美的积木模型。</p>
|
||||
<p><a class="glightbox" href="../what_is_dsa.assets/assembling_blocks.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="拼装积木" src="../what_is_dsa.assets/assembling_blocks.png" /></a></p>
|
||||
<p><a class="glightbox" href="../what_is_dsa.assets/assembling_blocks.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="拼装积木" class="animation-figure" src="../what_is_dsa.assets/assembling_blocks.png" /></a></p>
|
||||
<p align="center"> 图 1-5 拼装积木 </p>
|
||||
|
||||
<p>两者的详细对应关系如表 1-1 所示。</p>
|
||||
|
@ -3387,7 +3387,7 @@
|
||||
<li><strong>数据结构</strong>:基本数据类型,数据结构的分类方法。数组、链表、栈、队列、哈希表、树、堆、图等数据结构的定义、优缺点、常用操作、常见类型、典型应用、实现方法等。</li>
|
||||
<li><strong>算法</strong>:搜索、排序、分治、回溯、动态规划、贪心等算法的定义、优缺点、效率、应用场景、解题步骤、示例题目等。</li>
|
||||
</ul>
|
||||
<p><a class="glightbox" href="../about_the_book.assets/hello_algo_mindmap.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="Hello 算法内容结构" src="../about_the_book.assets/hello_algo_mindmap.jpg" /></a></p>
|
||||
<p><a class="glightbox" href="../about_the_book.assets/hello_algo_mindmap.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="Hello 算法内容结构" class="animation-figure" src="../about_the_book.assets/hello_algo_mindmap.jpg" /></a></p>
|
||||
<p align="center"> 图 0-1 Hello 算法内容结构 </p>
|
||||
|
||||
<h2 id="013">0.1.3 致谢<a class="headerlink" href="#013" title="Permanent link">¶</a></h2>
|
||||
|
@ -3290,7 +3290,7 @@
|
||||
<!-- Page content -->
|
||||
<h1 id="0">第 0 章 前言<a class="headerlink" href="#0" title="Permanent link">¶</a></h1>
|
||||
<div class="center-table">
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_preface.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="前言" src="../assets/covers/chapter_preface.jpg" width="600" /></a></p>
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_preface.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="前言" class="cover-image" src="../assets/covers/chapter_preface.jpg" /></a></p>
|
||||
</div>
|
||||
<div class="admonition abstract">
|
||||
<p class="admonition-title">Abstract</p>
|
||||
|
@ -3544,14 +3544,14 @@
|
||||
<h2 id="022">0.2.2 在动画图解中高效学习<a class="headerlink" href="#022" title="Permanent link">¶</a></h2>
|
||||
<p>相较于文字,视频和图片具有更高的信息密度和结构化程度,更易于理解。在本书中,<strong>重点和难点知识将主要通过动画和图解形式展示</strong>,而文字则作为动画和图片的解释与补充。</p>
|
||||
<p>如果你在阅读本书时,发现某段内容提供了图 0-2 所示的动画或图解,<strong>请以图为主、以文字为辅</strong>,综合两者来理解内容。</p>
|
||||
<p><a class="glightbox" href="../../index.assets/animation.gif" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="动画图解示例" src="../../index.assets/animation.gif" /></a></p>
|
||||
<p><a class="glightbox" href="../../index.assets/animation.gif" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="动画图解示例" class="animation-figure" src="../../index.assets/animation.gif" /></a></p>
|
||||
<p align="center"> 图 0-2 动画图解示例 </p>
|
||||
|
||||
<h2 id="023">0.2.3 在代码实践中加深理解<a class="headerlink" href="#023" title="Permanent link">¶</a></h2>
|
||||
<p>本书的配套代码被托管在 <a href="https://github.com/krahets/hello-algo">GitHub 仓库</a>。如图 0-3 所示,<strong>源代码附有测试样例,可一键运行</strong>。</p>
|
||||
<p>如果时间允许,<strong>建议你参照代码自行敲一遍</strong>。如果学习时间有限,请至少通读并运行所有代码。</p>
|
||||
<p>与阅读代码相比,编写代码的过程往往能带来更多收获。<strong>动手学,才是真的学</strong>。</p>
|
||||
<p><a class="glightbox" href="../../index.assets/running_code.gif" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="运行代码示例" src="../../index.assets/running_code.gif" /></a></p>
|
||||
<p><a class="glightbox" href="../../index.assets/running_code.gif" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="运行代码示例" class="animation-figure" src="../../index.assets/running_code.gif" /></a></p>
|
||||
<p align="center"> 图 0-3 运行代码示例 </p>
|
||||
|
||||
<p>运行代码的前置工作主要分为三步。</p>
|
||||
@ -3560,17 +3560,17 @@
|
||||
<div class="highlight"><pre><span></span><code><a id="__codelineno-12-1" name="__codelineno-12-1" href="#__codelineno-12-1"></a>git<span class="w"> </span>clone<span class="w"> </span>https://github.com/krahets/hello-algo.git
|
||||
</code></pre></div>
|
||||
<p>当然,你也可以在图 0-4 所示的位置,点击“Download ZIP”直接下载代码压缩包,然后在本地解压即可。</p>
|
||||
<p><a class="glightbox" href="../suggestions.assets/download_code.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="克隆仓库与下载代码" src="../suggestions.assets/download_code.png" /></a></p>
|
||||
<p><a class="glightbox" href="../suggestions.assets/download_code.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="克隆仓库与下载代码" class="animation-figure" src="../suggestions.assets/download_code.png" /></a></p>
|
||||
<p align="center"> 图 0-4 克隆仓库与下载代码 </p>
|
||||
|
||||
<p><strong>第三步:运行源代码</strong>。如图 0-5 所示,对于顶部标有文件名称的代码块,我们可以在仓库的 <code>codes</code> 文件夹内找到对应的源代码文件。源代码文件可一键运行,将帮助你节省不必要的调试时间,让你能够专注于学习内容。</p>
|
||||
<p><a class="glightbox" href="../suggestions.assets/code_md_to_repo.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="代码块与对应的源代码文件" src="../suggestions.assets/code_md_to_repo.png" /></a></p>
|
||||
<p><a class="glightbox" href="../suggestions.assets/code_md_to_repo.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="代码块与对应的源代码文件" class="animation-figure" src="../suggestions.assets/code_md_to_repo.png" /></a></p>
|
||||
<p align="center"> 图 0-5 代码块与对应的源代码文件 </p>
|
||||
|
||||
<h2 id="024">0.2.4 在提问讨论中共同成长<a class="headerlink" href="#024" title="Permanent link">¶</a></h2>
|
||||
<p>在阅读本书时,请不要轻易跳过那些没学明白的知识点。<strong>欢迎在评论区提出你的问题</strong>,我和小伙伴们将竭诚为你解答,一般情况下可在两天内回复。</p>
|
||||
<p>如图 0-6 所示,每篇文章的底部都配有评论区。希望你能多关注评论区的内容。一方面,你可以了解大家遇到的问题,从而查漏补缺,激发更深入的思考。另一方面,期待你能慷慨地回答其他小伙伴的问题,分享您的见解,帮助他人进步。</p>
|
||||
<p><a class="glightbox" href="../../index.assets/comment.gif" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="评论区示例" src="../../index.assets/comment.gif" /></a></p>
|
||||
<p><a class="glightbox" href="../../index.assets/comment.gif" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="评论区示例" class="animation-figure" src="../../index.assets/comment.gif" /></a></p>
|
||||
<p align="center"> 图 0-6 评论区示例 </p>
|
||||
|
||||
<h2 id="025">0.2.5 算法学习路线<a class="headerlink" href="#025" title="Permanent link">¶</a></h2>
|
||||
@ -3581,7 +3581,7 @@
|
||||
<li><strong>搭建知识体系</strong>。在学习方面,我们可以阅读算法专栏文章、解题框架和算法教材,以不断丰富知识体系。在刷题方面,可以尝试采用进阶刷题策略,如按专题分类、一题多解、一解多题等,相关的刷题心得可以在各个社区找到。</li>
|
||||
</ol>
|
||||
<p>如图 0-7 所示,本书内容主要涵盖“第一阶段”,旨在帮助你更高效地展开第二和第三阶段的学习。</p>
|
||||
<p><a class="glightbox" href="../suggestions.assets/learning_route.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="算法学习路线" src="../suggestions.assets/learning_route.png" /></a></p>
|
||||
<p><a class="glightbox" href="../suggestions.assets/learning_route.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="算法学习路线" class="animation-figure" src="../suggestions.assets/learning_route.png" /></a></p>
|
||||
<p align="center"> 图 0-7 算法学习路线 </p>
|
||||
|
||||
<!-- Source file information -->
|
||||
|
@ -3357,7 +3357,7 @@
|
||||
<p class="admonition-title">Question</p>
|
||||
<p>给定一个长度为 <span class="arithmatex">\(n\)</span> 的数组 <code>nums</code> ,元素按从小到大的顺序排列,数组不包含重复元素。请查找并返回元素 <code>target</code> 在该数组中的索引。若数组不包含该元素,则返回 <span class="arithmatex">\(-1\)</span> 。</p>
|
||||
</div>
|
||||
<p><a class="glightbox" href="../binary_search.assets/binary_search_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二分查找示例数据" src="../binary_search.assets/binary_search_example.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search.assets/binary_search_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二分查找示例数据" class="animation-figure" src="../binary_search.assets/binary_search_example.png" /></a></p>
|
||||
<p align="center"> 图 10-1 二分查找示例数据 </p>
|
||||
|
||||
<p>如图 10-2 所示,我们先初始化指针 <span class="arithmatex">\(i = 0\)</span> 和 <span class="arithmatex">\(j = n - 1\)</span> ,分别指向数组首元素和尾元素,代表搜索区间 <span class="arithmatex">\([0, n - 1]\)</span> 。请注意,中括号表示闭区间,其包含边界值本身。</p>
|
||||
@ -3375,25 +3375,25 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="1:7"><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" /><div class="tabbed-labels"><label for="__tabbed_1_1"><1></label><label for="__tabbed_1_2"><2></label><label for="__tabbed_1_3"><3></label><label for="__tabbed_1_4"><4></label><label for="__tabbed_1_5"><5></label><label for="__tabbed_1_6"><6></label><label for="__tabbed_1_7"><7></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_search.assets/binary_search_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二分查找流程" src="../binary_search.assets/binary_search_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search.assets/binary_search_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二分查找流程" class="animation-figure" src="../binary_search.assets/binary_search_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_search.assets/binary_search_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_step2" src="../binary_search.assets/binary_search_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search.assets/binary_search_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_step2" class="animation-figure" src="../binary_search.assets/binary_search_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_search.assets/binary_search_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_step3" src="../binary_search.assets/binary_search_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search.assets/binary_search_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_step3" class="animation-figure" src="../binary_search.assets/binary_search_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_search.assets/binary_search_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_step4" src="../binary_search.assets/binary_search_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search.assets/binary_search_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_step4" class="animation-figure" src="../binary_search.assets/binary_search_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_search.assets/binary_search_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_step5" src="../binary_search.assets/binary_search_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search.assets/binary_search_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_step5" class="animation-figure" src="../binary_search.assets/binary_search_step5.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_search.assets/binary_search_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_step6" src="../binary_search.assets/binary_search_step6.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search.assets/binary_search_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_step6" class="animation-figure" src="../binary_search.assets/binary_search_step6.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_search.assets/binary_search_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_step7" src="../binary_search.assets/binary_search_step7.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search.assets/binary_search_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_step7" class="animation-figure" src="../binary_search.assets/binary_search_step7.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -3929,7 +3929,7 @@
|
||||
</div>
|
||||
<p>如图 10-3 所示,在两种区间表示下,二分查找算法的初始化、循环条件和缩小区间操作皆有所不同。</p>
|
||||
<p>由于“双闭区间”表示中的左右边界都被定义为闭区间,因此指针 <span class="arithmatex">\(i\)</span> 和 <span class="arithmatex">\(j\)</span> 缩小区间操作也是对称的。这样更不容易出错,<strong>因此一般建议采用“双闭区间”的写法</strong>。</p>
|
||||
<p><a class="glightbox" href="../binary_search.assets/binary_search_ranges.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="两种区间定义" src="../binary_search.assets/binary_search_ranges.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search.assets/binary_search_ranges.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="两种区间定义" class="animation-figure" src="../binary_search.assets/binary_search_ranges.png" /></a></p>
|
||||
<p align="center"> 图 10-3 两种区间定义 </p>
|
||||
|
||||
<h2 id="1012">10.1.2 优点与局限性<a class="headerlink" href="#1012" title="Permanent link">¶</a></h2>
|
||||
|
@ -3570,7 +3570,7 @@
|
||||
<h3 id="1">1. 复用查找左边界<a class="headerlink" href="#1" title="Permanent link">¶</a></h3>
|
||||
<p>实际上,我们可以利用查找最左元素的函数来查找最右元素,具体方法为:<strong>将查找最右一个 <code>target</code> 转化为查找最左一个 <code>target + 1</code></strong>。</p>
|
||||
<p>如图 10-7 所示,查找完成后,指针 <span class="arithmatex">\(i\)</span> 指向最左一个 <code>target + 1</code>(如果存在),而 <span class="arithmatex">\(j\)</span> 指向最右一个 <code>target</code> ,<strong>因此返回 <span class="arithmatex">\(j\)</span> 即可</strong>。</p>
|
||||
<p><a class="glightbox" href="../binary_search_edge.assets/binary_search_right_edge_by_left_edge.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="将查找右边界转化为查找左边界" src="../binary_search_edge.assets/binary_search_right_edge_by_left_edge.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_edge.assets/binary_search_right_edge_by_left_edge.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="将查找右边界转化为查找左边界" class="animation-figure" src="../binary_search_edge.assets/binary_search_right_edge_by_left_edge.png" /></a></p>
|
||||
<p align="center"> 图 10-7 将查找右边界转化为查找左边界 </p>
|
||||
|
||||
<p>请注意,返回的插入点是 <span class="arithmatex">\(i\)</span> ,因此需要将其减 <span class="arithmatex">\(1\)</span> ,从而获得 <span class="arithmatex">\(j\)</span> 。</p>
|
||||
@ -3763,7 +3763,7 @@
|
||||
<li>查找最左一个 <code>target</code> :可以转化为查找 <code>target - 0.5</code> ,并返回指针 <span class="arithmatex">\(i\)</span> 。</li>
|
||||
<li>查找最右一个 <code>target</code> :可以转化为查找 <code>target + 0.5</code> ,并返回指针 <span class="arithmatex">\(j\)</span> 。</li>
|
||||
</ul>
|
||||
<p><a class="glightbox" href="../binary_search_edge.assets/binary_search_edge_by_element.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="将查找边界转化为查找元素" src="../binary_search_edge.assets/binary_search_edge_by_element.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_edge.assets/binary_search_edge_by_element.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="将查找边界转化为查找元素" class="animation-figure" src="../binary_search_edge.assets/binary_search_edge_by_element.png" /></a></p>
|
||||
<p align="center"> 图 10-8 将查找边界转化为查找元素 </p>
|
||||
|
||||
<p>代码在此省略,值得注意以下两点。</p>
|
||||
|
@ -3358,7 +3358,7 @@
|
||||
<p class="admonition-title">Question</p>
|
||||
<p>给定一个长度为 <span class="arithmatex">\(n\)</span> 的有序数组 <code>nums</code> 和一个元素 <code>target</code> ,数组不存在重复元素。现将 <code>target</code> 插入到数组 <code>nums</code> 中,并保持其有序性。若数组中已存在元素 <code>target</code> ,则插入到其左方。请返回插入后 <code>target</code> 在数组中的索引。</p>
|
||||
</div>
|
||||
<p><a class="glightbox" href="../binary_search_insertion.assets/binary_search_insertion_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二分查找插入点示例数据" src="../binary_search_insertion.assets/binary_search_insertion_example.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_insertion.assets/binary_search_insertion_example.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二分查找插入点示例数据" class="animation-figure" src="../binary_search_insertion.assets/binary_search_insertion_example.png" /></a></p>
|
||||
<p align="center"> 图 10-4 二分查找插入点示例数据 </p>
|
||||
|
||||
<p>如果想要复用上节的二分查找代码,则需要回答以下两个问题。</p>
|
||||
@ -3602,7 +3602,7 @@
|
||||
<li>执行二分查找,得到任意一个 <code>target</code> 的索引,记为 <span class="arithmatex">\(k\)</span> 。</li>
|
||||
<li>从索引 <span class="arithmatex">\(k\)</span> 开始,向左进行线性遍历,当找到最左边的 <code>target</code> 时返回。</li>
|
||||
</ol>
|
||||
<p><a class="glightbox" href="../binary_search_insertion.assets/binary_search_insertion_naive.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="线性查找重复元素的插入点" src="../binary_search_insertion.assets/binary_search_insertion_naive.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_insertion.assets/binary_search_insertion_naive.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="线性查找重复元素的插入点" class="animation-figure" src="../binary_search_insertion.assets/binary_search_insertion_naive.png" /></a></p>
|
||||
<p align="center"> 图 10-5 线性查找重复元素的插入点 </p>
|
||||
|
||||
<p>此方法虽然可用,但其包含线性查找,因此时间复杂度为 <span class="arithmatex">\(O(n)\)</span> 。当数组中存在很多重复的 <code>target</code> 时,该方法效率很低。</p>
|
||||
@ -3615,28 +3615,28 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="2:8"><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" /><div class="tabbed-labels"><label for="__tabbed_2_1"><1></label><label for="__tabbed_2_2"><2></label><label for="__tabbed_2_3"><3></label><label for="__tabbed_2_4"><4></label><label for="__tabbed_2_5"><5></label><label for="__tabbed_2_6"><6></label><label for="__tabbed_2_7"><7></label><label for="__tabbed_2_8"><8></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_search_insertion.assets/binary_search_insertion_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二分查找重复元素的插入点的步骤" src="../binary_search_insertion.assets/binary_search_insertion_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_insertion.assets/binary_search_insertion_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二分查找重复元素的插入点的步骤" class="animation-figure" src="../binary_search_insertion.assets/binary_search_insertion_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_search_insertion.assets/binary_search_insertion_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_insertion_step2" src="../binary_search_insertion.assets/binary_search_insertion_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_insertion.assets/binary_search_insertion_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_insertion_step2" class="animation-figure" src="../binary_search_insertion.assets/binary_search_insertion_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_search_insertion.assets/binary_search_insertion_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_insertion_step3" src="../binary_search_insertion.assets/binary_search_insertion_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_insertion.assets/binary_search_insertion_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_insertion_step3" class="animation-figure" src="../binary_search_insertion.assets/binary_search_insertion_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_search_insertion.assets/binary_search_insertion_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_insertion_step4" src="../binary_search_insertion.assets/binary_search_insertion_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_insertion.assets/binary_search_insertion_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_insertion_step4" class="animation-figure" src="../binary_search_insertion.assets/binary_search_insertion_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_search_insertion.assets/binary_search_insertion_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_insertion_step5" src="../binary_search_insertion.assets/binary_search_insertion_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_insertion.assets/binary_search_insertion_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_insertion_step5" class="animation-figure" src="../binary_search_insertion.assets/binary_search_insertion_step5.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_search_insertion.assets/binary_search_insertion_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_insertion_step6" src="../binary_search_insertion.assets/binary_search_insertion_step6.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_insertion.assets/binary_search_insertion_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_insertion_step6" class="animation-figure" src="../binary_search_insertion.assets/binary_search_insertion_step6.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_search_insertion.assets/binary_search_insertion_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_insertion_step7" src="../binary_search_insertion.assets/binary_search_insertion_step7.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_insertion.assets/binary_search_insertion_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_insertion_step7" class="animation-figure" src="../binary_search_insertion.assets/binary_search_insertion_step7.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_search_insertion.assets/binary_search_insertion_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_insertion_step8" src="../binary_search_insertion.assets/binary_search_insertion_step8.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_insertion.assets/binary_search_insertion_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="binary_search_insertion_step8" class="animation-figure" src="../binary_search_insertion.assets/binary_search_insertion_step8.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3292,7 +3292,7 @@
|
||||
<!-- Page content -->
|
||||
<h1 id="10">第 10 章 搜索<a class="headerlink" href="#10" title="Permanent link">¶</a></h1>
|
||||
<div class="center-table">
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_searching.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="搜索" src="../assets/covers/chapter_searching.jpg" width="600" /></a></p>
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_searching.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="搜索" class="cover-image" src="../assets/covers/chapter_searching.jpg" /></a></p>
|
||||
</div>
|
||||
<div class="admonition abstract">
|
||||
<p class="admonition-title">Abstract</p>
|
||||
|
@ -3359,7 +3359,7 @@
|
||||
</div>
|
||||
<h2 id="1041">10.4.1 线性查找:以时间换空间<a class="headerlink" href="#1041" title="Permanent link">¶</a></h2>
|
||||
<p>考虑直接遍历所有可能的组合。如图 10-9 所示,我们开启一个两层循环,在每轮中判断两个整数的和是否为 <code>target</code> ,若是则返回它们的索引。</p>
|
||||
<p><a class="glightbox" href="../replace_linear_by_hashing.assets/two_sum_brute_force.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="线性查找求解两数之和" src="../replace_linear_by_hashing.assets/two_sum_brute_force.png" /></a></p>
|
||||
<p><a class="glightbox" href="../replace_linear_by_hashing.assets/two_sum_brute_force.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="线性查找求解两数之和" class="animation-figure" src="../replace_linear_by_hashing.assets/two_sum_brute_force.png" /></a></p>
|
||||
<p align="center"> 图 10-9 线性查找求解两数之和 </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>
|
||||
@ -3561,13 +3561,13 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="2:3"><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" /><div class="tabbed-labels"><label for="__tabbed_2_1"><1></label><label for="__tabbed_2_2"><2></label><label for="__tabbed_2_3"><3></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../replace_linear_by_hashing.assets/two_sum_hashtable_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="辅助哈希表求解两数之和" src="../replace_linear_by_hashing.assets/two_sum_hashtable_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../replace_linear_by_hashing.assets/two_sum_hashtable_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="辅助哈希表求解两数之和" class="animation-figure" src="../replace_linear_by_hashing.assets/two_sum_hashtable_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../replace_linear_by_hashing.assets/two_sum_hashtable_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="two_sum_hashtable_step2" src="../replace_linear_by_hashing.assets/two_sum_hashtable_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../replace_linear_by_hashing.assets/two_sum_hashtable_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="two_sum_hashtable_step2" class="animation-figure" src="../replace_linear_by_hashing.assets/two_sum_hashtable_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../replace_linear_by_hashing.assets/two_sum_hashtable_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="two_sum_hashtable_step3" src="../replace_linear_by_hashing.assets/two_sum_hashtable_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../replace_linear_by_hashing.assets/two_sum_hashtable_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="two_sum_hashtable_step3" class="animation-figure" src="../replace_linear_by_hashing.assets/two_sum_hashtable_step3.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3396,7 +3396,7 @@
|
||||
</div>
|
||||
<h2 id="1053">10.5.3 搜索方法选取<a class="headerlink" href="#1053" title="Permanent link">¶</a></h2>
|
||||
<p>给定大小为 <span class="arithmatex">\(n\)</span> 的一组数据,我们可以使用线性搜索、二分查找、树查找、哈希查找等多种方法在该数据中搜索目标元素。各个方法的工作原理如图 10-11 所示。</p>
|
||||
<p><a class="glightbox" href="../searching_algorithm_revisited.assets/searching_algorithms.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="多种搜索策略" src="../searching_algorithm_revisited.assets/searching_algorithms.png" /></a></p>
|
||||
<p><a class="glightbox" href="../searching_algorithm_revisited.assets/searching_algorithms.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="多种搜索策略" class="animation-figure" src="../searching_algorithm_revisited.assets/searching_algorithms.png" /></a></p>
|
||||
<p align="center"> 图 10-11 多种搜索策略 </p>
|
||||
|
||||
<p>上述几种方法的操作效率与特性如表 10-1 所示。</p>
|
||||
|
@ -3371,25 +3371,25 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="1:7"><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" /><div class="tabbed-labels"><label for="__tabbed_1_1"><1></label><label for="__tabbed_1_2"><2></label><label for="__tabbed_1_3"><3></label><label for="__tabbed_1_4"><4></label><label for="__tabbed_1_5"><5></label><label for="__tabbed_1_6"><6></label><label for="__tabbed_1_7"><7></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../bubble_sort.assets/bubble_operation_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="利用元素交换操作模拟冒泡" src="../bubble_sort.assets/bubble_operation_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../bubble_sort.assets/bubble_operation_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="利用元素交换操作模拟冒泡" class="animation-figure" src="../bubble_sort.assets/bubble_operation_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../bubble_sort.assets/bubble_operation_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bubble_operation_step2" src="../bubble_sort.assets/bubble_operation_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../bubble_sort.assets/bubble_operation_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bubble_operation_step2" class="animation-figure" src="../bubble_sort.assets/bubble_operation_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../bubble_sort.assets/bubble_operation_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bubble_operation_step3" src="../bubble_sort.assets/bubble_operation_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../bubble_sort.assets/bubble_operation_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bubble_operation_step3" class="animation-figure" src="../bubble_sort.assets/bubble_operation_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../bubble_sort.assets/bubble_operation_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bubble_operation_step4" src="../bubble_sort.assets/bubble_operation_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../bubble_sort.assets/bubble_operation_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bubble_operation_step4" class="animation-figure" src="../bubble_sort.assets/bubble_operation_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../bubble_sort.assets/bubble_operation_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bubble_operation_step5" src="../bubble_sort.assets/bubble_operation_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../bubble_sort.assets/bubble_operation_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bubble_operation_step5" class="animation-figure" src="../bubble_sort.assets/bubble_operation_step5.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../bubble_sort.assets/bubble_operation_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bubble_operation_step6" src="../bubble_sort.assets/bubble_operation_step6.png" /></a></p>
|
||||
<p><a class="glightbox" href="../bubble_sort.assets/bubble_operation_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bubble_operation_step6" class="animation-figure" src="../bubble_sort.assets/bubble_operation_step6.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../bubble_sort.assets/bubble_operation_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bubble_operation_step7" src="../bubble_sort.assets/bubble_operation_step7.png" /></a></p>
|
||||
<p><a class="glightbox" href="../bubble_sort.assets/bubble_operation_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bubble_operation_step7" class="animation-figure" src="../bubble_sort.assets/bubble_operation_step7.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -3403,7 +3403,7 @@
|
||||
<li>以此类推,经过 <span class="arithmatex">\(n - 1\)</span> 轮“冒泡”后,<strong>前 <span class="arithmatex">\(n - 1\)</span> 大的元素都被交换至正确位置</strong>。</li>
|
||||
<li>仅剩的一个元素必定是最小元素,无须排序,因此数组排序完成。</li>
|
||||
</ol>
|
||||
<p><a class="glightbox" href="../bubble_sort.assets/bubble_sort_overview.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="冒泡排序流程" src="../bubble_sort.assets/bubble_sort_overview.png" /></a></p>
|
||||
<p><a class="glightbox" href="../bubble_sort.assets/bubble_sort_overview.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="冒泡排序流程" class="animation-figure" src="../bubble_sort.assets/bubble_sort_overview.png" /></a></p>
|
||||
<p align="center"> 图 11-5 冒泡排序流程 </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>
|
||||
|
@ -3375,7 +3375,7 @@
|
||||
<li>对每个桶分别执行排序(本文采用编程语言的内置排序函数)。</li>
|
||||
<li>按照桶的从小到大的顺序,合并结果。</li>
|
||||
</ol>
|
||||
<p><a class="glightbox" href="../bucket_sort.assets/bucket_sort_overview.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="桶排序算法流程" src="../bucket_sort.assets/bucket_sort_overview.png" /></a></p>
|
||||
<p><a class="glightbox" href="../bucket_sort.assets/bucket_sort_overview.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="桶排序算法流程" class="animation-figure" src="../bucket_sort.assets/bucket_sort_overview.png" /></a></p>
|
||||
<p align="center"> 图 11-13 桶排序算法流程 </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>
|
||||
@ -3742,12 +3742,12 @@
|
||||
<p>桶排序的时间复杂度理论上可以达到 <span class="arithmatex">\(O(n)\)</span> ,<strong>关键在于将元素均匀分配到各个桶中</strong>,因为实际数据往往不是均匀分布的。例如,我们想要将淘宝上的所有商品按价格范围平均分配到 10 个桶中,但商品价格分布不均,低于 100 元的非常多,高于 1000 元的非常少。若将价格区间平均划分为 10 份,各个桶中的商品数量差距会非常大。</p>
|
||||
<p>为实现平均分配,我们可以先设定一个大致的分界线,将数据粗略地分到 3 个桶中。<strong>分配完毕后,再将商品较多的桶继续划分为 3 个桶,直至所有桶中的元素数量大致相等</strong>。</p>
|
||||
<p>如图 11-14 所示,这种方法本质上是创建一个递归树,目标是让叶节点的值尽可能平均。当然,不一定要每轮将数据划分为 3 个桶,具体划分方式可根据数据特点灵活选择。</p>
|
||||
<p><a class="glightbox" href="../bucket_sort.assets/scatter_in_buckets_recursively.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="递归划分桶" src="../bucket_sort.assets/scatter_in_buckets_recursively.png" /></a></p>
|
||||
<p><a class="glightbox" href="../bucket_sort.assets/scatter_in_buckets_recursively.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="递归划分桶" class="animation-figure" src="../bucket_sort.assets/scatter_in_buckets_recursively.png" /></a></p>
|
||||
<p align="center"> 图 11-14 递归划分桶 </p>
|
||||
|
||||
<p>如果我们提前知道商品价格的概率分布,<strong>则可以根据数据概率分布设置每个桶的价格分界线</strong>。值得注意的是,数据分布并不一定需要特意统计,也可以根据数据特点采用某种概率模型进行近似。</p>
|
||||
<p>如图 11-15 所示,我们假设商品价格服从正态分布,这样就可以合理地设定价格区间,从而将商品平均分配到各个桶中。</p>
|
||||
<p><a class="glightbox" href="../bucket_sort.assets/scatter_in_buckets_distribution.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="根据概率分布划分桶" src="../bucket_sort.assets/scatter_in_buckets_distribution.png" /></a></p>
|
||||
<p><a class="glightbox" href="../bucket_sort.assets/scatter_in_buckets_distribution.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="根据概率分布划分桶" class="animation-figure" src="../bucket_sort.assets/scatter_in_buckets_distribution.png" /></a></p>
|
||||
<p align="center"> 图 11-15 根据概率分布划分桶 </p>
|
||||
|
||||
<!-- Source file information -->
|
||||
|
@ -3388,7 +3388,7 @@
|
||||
<li><strong>借助 <code>counter</code> 统计 <code>nums</code> 中各数字的出现次数</strong>,其中 <code>counter[num]</code> 对应数字 <code>num</code> 的出现次数。统计方法很简单,只需遍历 <code>nums</code>(设当前数字为 <code>num</code>),每轮将 <code>counter[num]</code> 增加 <span class="arithmatex">\(1\)</span> 即可。</li>
|
||||
<li><strong>由于 <code>counter</code> 的各个索引天然有序,因此相当于所有数字已经被排序好了</strong>。接下来,我们遍历 <code>counter</code> ,根据各数字的出现次数,将它们按从小到大的顺序填入 <code>nums</code> 即可。</li>
|
||||
</ol>
|
||||
<p><a class="glightbox" href="../counting_sort.assets/counting_sort_overview.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="计数排序流程" src="../counting_sort.assets/counting_sort_overview.png" /></a></p>
|
||||
<p><a class="glightbox" href="../counting_sort.assets/counting_sort_overview.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="计数排序流程" class="animation-figure" src="../counting_sort.assets/counting_sort_overview.png" /></a></p>
|
||||
<p align="center"> 图 11-16 计数排序流程 </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>
|
||||
@ -3689,28 +3689,28 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="2:8"><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" /><div class="tabbed-labels"><label for="__tabbed_2_1"><1></label><label for="__tabbed_2_2"><2></label><label for="__tabbed_2_3"><3></label><label for="__tabbed_2_4"><4></label><label for="__tabbed_2_5"><5></label><label for="__tabbed_2_6"><6></label><label for="__tabbed_2_7"><7></label><label for="__tabbed_2_8"><8></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../counting_sort.assets/counting_sort_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="计数排序步骤" src="../counting_sort.assets/counting_sort_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../counting_sort.assets/counting_sort_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="计数排序步骤" class="animation-figure" src="../counting_sort.assets/counting_sort_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../counting_sort.assets/counting_sort_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="counting_sort_step2" src="../counting_sort.assets/counting_sort_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../counting_sort.assets/counting_sort_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="counting_sort_step2" class="animation-figure" src="../counting_sort.assets/counting_sort_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../counting_sort.assets/counting_sort_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="counting_sort_step3" src="../counting_sort.assets/counting_sort_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../counting_sort.assets/counting_sort_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="counting_sort_step3" class="animation-figure" src="../counting_sort.assets/counting_sort_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../counting_sort.assets/counting_sort_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="counting_sort_step4" src="../counting_sort.assets/counting_sort_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../counting_sort.assets/counting_sort_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="counting_sort_step4" class="animation-figure" src="../counting_sort.assets/counting_sort_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../counting_sort.assets/counting_sort_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="counting_sort_step5" src="../counting_sort.assets/counting_sort_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../counting_sort.assets/counting_sort_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="counting_sort_step5" class="animation-figure" src="../counting_sort.assets/counting_sort_step5.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../counting_sort.assets/counting_sort_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="counting_sort_step6" src="../counting_sort.assets/counting_sort_step6.png" /></a></p>
|
||||
<p><a class="glightbox" href="../counting_sort.assets/counting_sort_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="counting_sort_step6" class="animation-figure" src="../counting_sort.assets/counting_sort_step6.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../counting_sort.assets/counting_sort_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="counting_sort_step7" src="../counting_sort.assets/counting_sort_step7.png" /></a></p>
|
||||
<p><a class="glightbox" href="../counting_sort.assets/counting_sort_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="counting_sort_step7" class="animation-figure" src="../counting_sort.assets/counting_sort_step7.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../counting_sort.assets/counting_sort_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="counting_sort_step8" src="../counting_sort.assets/counting_sort_step8.png" /></a></p>
|
||||
<p><a class="glightbox" href="../counting_sort.assets/counting_sort_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="counting_sort_step8" class="animation-figure" src="../counting_sort.assets/counting_sort_step8.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3377,40 +3377,40 @@
|
||||
<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"><1></label><label for="__tabbed_1_2"><2></label><label for="__tabbed_1_3"><3></label><label for="__tabbed_1_4"><4></label><label for="__tabbed_1_5"><5></label><label for="__tabbed_1_6"><6></label><label for="__tabbed_1_7"><7></label><label for="__tabbed_1_8"><8></label><label for="__tabbed_1_9"><9></label><label for="__tabbed_1_10"><10></label><label for="__tabbed_1_11"><11></label><label for="__tabbed_1_12"><12></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="堆排序步骤" src="../heap_sort.assets/heap_sort_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="堆排序步骤" class="animation-figure" src="../heap_sort.assets/heap_sort_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_sort_step2" src="../heap_sort.assets/heap_sort_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_sort_step2" class="animation-figure" src="../heap_sort.assets/heap_sort_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_sort_step3" src="../heap_sort.assets/heap_sort_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_sort_step3" class="animation-figure" src="../heap_sort.assets/heap_sort_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_sort_step4" src="../heap_sort.assets/heap_sort_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_sort_step4" class="animation-figure" src="../heap_sort.assets/heap_sort_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_sort_step5" src="../heap_sort.assets/heap_sort_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_sort_step5" class="animation-figure" src="../heap_sort.assets/heap_sort_step5.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_sort_step6" src="../heap_sort.assets/heap_sort_step6.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_sort_step6" class="animation-figure" src="../heap_sort.assets/heap_sort_step6.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_sort_step7" src="../heap_sort.assets/heap_sort_step7.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_sort_step7" class="animation-figure" src="../heap_sort.assets/heap_sort_step7.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_sort_step8" src="../heap_sort.assets/heap_sort_step8.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_sort_step8" class="animation-figure" src="../heap_sort.assets/heap_sort_step8.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_sort_step9" src="../heap_sort.assets/heap_sort_step9.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_sort_step9" class="animation-figure" src="../heap_sort.assets/heap_sort_step9.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_sort_step10" src="../heap_sort.assets/heap_sort_step10.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_sort_step10" class="animation-figure" src="../heap_sort.assets/heap_sort_step10.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step11.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_sort_step11" src="../heap_sort.assets/heap_sort_step11.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step11.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_sort_step11" class="animation-figure" src="../heap_sort.assets/heap_sort_step11.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step12.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_sort_step12" src="../heap_sort.assets/heap_sort_step12.png" /></a></p>
|
||||
<p><a class="glightbox" href="../heap_sort.assets/heap_sort_step12.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="heap_sort_step12" class="animation-figure" src="../heap_sort.assets/heap_sort_step12.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3292,7 +3292,7 @@
|
||||
<!-- Page content -->
|
||||
<h1 id="11">第 11 章 排序<a class="headerlink" href="#11" title="Permanent link">¶</a></h1>
|
||||
<div class="center-table">
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_sorting.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="排序" src="../assets/covers/chapter_sorting.jpg" width="600" /></a></p>
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_sorting.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="排序" class="cover-image" src="../assets/covers/chapter_sorting.jpg" /></a></p>
|
||||
</div>
|
||||
<div class="admonition abstract">
|
||||
<p class="admonition-title">Abstract</p>
|
||||
|
@ -3369,7 +3369,7 @@
|
||||
<p>「插入排序 insertion sort」是一种简单的排序算法,它的工作原理与手动整理一副牌的过程非常相似。</p>
|
||||
<p>具体来说,我们在未排序区间选择一个基准元素,将该元素与其左侧已排序区间的元素逐一比较大小,并将该元素插入到正确的位置。</p>
|
||||
<p>图 11-6 展示了数组插入元素的操作流程。设基准元素为 <code>base</code> ,我们需要将从目标索引到 <code>base</code> 之间的所有元素向右移动一位,然后再将 <code>base</code> 赋值给目标索引。</p>
|
||||
<p><a class="glightbox" href="../insertion_sort.assets/insertion_operation.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="单次插入操作" src="../insertion_sort.assets/insertion_operation.png" /></a></p>
|
||||
<p><a class="glightbox" href="../insertion_sort.assets/insertion_operation.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="单次插入操作" class="animation-figure" src="../insertion_sort.assets/insertion_operation.png" /></a></p>
|
||||
<p align="center"> 图 11-6 单次插入操作 </p>
|
||||
|
||||
<h2 id="1141">11.4.1 算法流程<a class="headerlink" href="#1141" title="Permanent link">¶</a></h2>
|
||||
@ -3380,7 +3380,7 @@
|
||||
<li>选取第 3 个元素作为 <code>base</code> ,将其插入到正确位置后,<strong>数组的前 3 个元素已排序</strong>。</li>
|
||||
<li>以此类推,在最后一轮中,选取最后一个元素作为 <code>base</code> ,将其插入到正确位置后,<strong>所有元素均已排序</strong>。</li>
|
||||
</ol>
|
||||
<p><a class="glightbox" href="../insertion_sort.assets/insertion_sort_overview.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="插入排序流程" src="../insertion_sort.assets/insertion_sort_overview.png" /></a></p>
|
||||
<p><a class="glightbox" href="../insertion_sort.assets/insertion_sort_overview.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="插入排序流程" class="animation-figure" src="../insertion_sort.assets/insertion_sort_overview.png" /></a></p>
|
||||
<p align="center"> 图 11-7 插入排序流程 </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>
|
||||
|
@ -3371,7 +3371,7 @@
|
||||
<li><strong>划分阶段</strong>:通过递归不断地将数组从中点处分开,将长数组的排序问题转换为短数组的排序问题。</li>
|
||||
<li><strong>合并阶段</strong>:当子数组长度为 1 时终止划分,开始合并,持续地将左右两个较短的有序数组合并为一个较长的有序数组,直至结束。</li>
|
||||
</ol>
|
||||
<p><a class="glightbox" href="../merge_sort.assets/merge_sort_overview.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="归并排序的划分与合并阶段" src="../merge_sort.assets/merge_sort_overview.png" /></a></p>
|
||||
<p><a class="glightbox" href="../merge_sort.assets/merge_sort_overview.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="归并排序的划分与合并阶段" class="animation-figure" src="../merge_sort.assets/merge_sort_overview.png" /></a></p>
|
||||
<p align="center"> 图 11-10 归并排序的划分与合并阶段 </p>
|
||||
|
||||
<h2 id="1161">11.6.1 算法流程<a class="headerlink" href="#1161" title="Permanent link">¶</a></h2>
|
||||
@ -3384,34 +3384,34 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="1:10"><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" /><div class="tabbed-labels"><label for="__tabbed_1_1"><1></label><label for="__tabbed_1_2"><2></label><label for="__tabbed_1_3"><3></label><label for="__tabbed_1_4"><4></label><label for="__tabbed_1_5"><5></label><label for="__tabbed_1_6"><6></label><label for="__tabbed_1_7"><7></label><label for="__tabbed_1_8"><8></label><label for="__tabbed_1_9"><9></label><label for="__tabbed_1_10"><10></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../merge_sort.assets/merge_sort_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="归并排序步骤" src="../merge_sort.assets/merge_sort_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../merge_sort.assets/merge_sort_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="归并排序步骤" class="animation-figure" src="../merge_sort.assets/merge_sort_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../merge_sort.assets/merge_sort_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="merge_sort_step2" src="../merge_sort.assets/merge_sort_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../merge_sort.assets/merge_sort_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="merge_sort_step2" class="animation-figure" src="../merge_sort.assets/merge_sort_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../merge_sort.assets/merge_sort_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="merge_sort_step3" src="../merge_sort.assets/merge_sort_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../merge_sort.assets/merge_sort_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="merge_sort_step3" class="animation-figure" src="../merge_sort.assets/merge_sort_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../merge_sort.assets/merge_sort_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="merge_sort_step4" src="../merge_sort.assets/merge_sort_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../merge_sort.assets/merge_sort_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="merge_sort_step4" class="animation-figure" src="../merge_sort.assets/merge_sort_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../merge_sort.assets/merge_sort_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="merge_sort_step5" src="../merge_sort.assets/merge_sort_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../merge_sort.assets/merge_sort_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="merge_sort_step5" class="animation-figure" src="../merge_sort.assets/merge_sort_step5.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../merge_sort.assets/merge_sort_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="merge_sort_step6" src="../merge_sort.assets/merge_sort_step6.png" /></a></p>
|
||||
<p><a class="glightbox" href="../merge_sort.assets/merge_sort_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="merge_sort_step6" class="animation-figure" src="../merge_sort.assets/merge_sort_step6.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../merge_sort.assets/merge_sort_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="merge_sort_step7" src="../merge_sort.assets/merge_sort_step7.png" /></a></p>
|
||||
<p><a class="glightbox" href="../merge_sort.assets/merge_sort_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="merge_sort_step7" class="animation-figure" src="../merge_sort.assets/merge_sort_step7.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../merge_sort.assets/merge_sort_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="merge_sort_step8" src="../merge_sort.assets/merge_sort_step8.png" /></a></p>
|
||||
<p><a class="glightbox" href="../merge_sort.assets/merge_sort_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="merge_sort_step8" class="animation-figure" src="../merge_sort.assets/merge_sort_step8.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../merge_sort.assets/merge_sort_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="merge_sort_step9" src="../merge_sort.assets/merge_sort_step9.png" /></a></p>
|
||||
<p><a class="glightbox" href="../merge_sort.assets/merge_sort_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="merge_sort_step9" class="animation-figure" src="../merge_sort.assets/merge_sort_step9.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../merge_sort.assets/merge_sort_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="merge_sort_step10" src="../merge_sort.assets/merge_sort_step10.png" /></a></p>
|
||||
<p><a class="glightbox" href="../merge_sort.assets/merge_sort_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="merge_sort_step10" class="animation-figure" src="../merge_sort.assets/merge_sort_step10.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3404,31 +3404,31 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="1:9"><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" /><div class="tabbed-labels"><label for="__tabbed_1_1"><1></label><label for="__tabbed_1_2"><2></label><label for="__tabbed_1_3"><3></label><label for="__tabbed_1_4"><4></label><label for="__tabbed_1_5"><5></label><label for="__tabbed_1_6"><6></label><label for="__tabbed_1_7"><7></label><label for="__tabbed_1_8"><8></label><label for="__tabbed_1_9"><9></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../quick_sort.assets/pivot_division_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="哨兵划分步骤" src="../quick_sort.assets/pivot_division_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../quick_sort.assets/pivot_division_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="哨兵划分步骤" class="animation-figure" src="../quick_sort.assets/pivot_division_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../quick_sort.assets/pivot_division_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="pivot_division_step2" src="../quick_sort.assets/pivot_division_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../quick_sort.assets/pivot_division_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="pivot_division_step2" class="animation-figure" src="../quick_sort.assets/pivot_division_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../quick_sort.assets/pivot_division_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="pivot_division_step3" src="../quick_sort.assets/pivot_division_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../quick_sort.assets/pivot_division_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="pivot_division_step3" class="animation-figure" src="../quick_sort.assets/pivot_division_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../quick_sort.assets/pivot_division_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="pivot_division_step4" src="../quick_sort.assets/pivot_division_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../quick_sort.assets/pivot_division_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="pivot_division_step4" class="animation-figure" src="../quick_sort.assets/pivot_division_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../quick_sort.assets/pivot_division_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="pivot_division_step5" src="../quick_sort.assets/pivot_division_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../quick_sort.assets/pivot_division_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="pivot_division_step5" class="animation-figure" src="../quick_sort.assets/pivot_division_step5.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../quick_sort.assets/pivot_division_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="pivot_division_step6" src="../quick_sort.assets/pivot_division_step6.png" /></a></p>
|
||||
<p><a class="glightbox" href="../quick_sort.assets/pivot_division_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="pivot_division_step6" class="animation-figure" src="../quick_sort.assets/pivot_division_step6.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../quick_sort.assets/pivot_division_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="pivot_division_step7" src="../quick_sort.assets/pivot_division_step7.png" /></a></p>
|
||||
<p><a class="glightbox" href="../quick_sort.assets/pivot_division_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="pivot_division_step7" class="animation-figure" src="../quick_sort.assets/pivot_division_step7.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../quick_sort.assets/pivot_division_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="pivot_division_step8" src="../quick_sort.assets/pivot_division_step8.png" /></a></p>
|
||||
<p><a class="glightbox" href="../quick_sort.assets/pivot_division_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="pivot_division_step8" class="animation-figure" src="../quick_sort.assets/pivot_division_step8.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../quick_sort.assets/pivot_division_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="pivot_division_step9" src="../quick_sort.assets/pivot_division_step9.png" /></a></p>
|
||||
<p><a class="glightbox" href="../quick_sort.assets/pivot_division_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="pivot_division_step9" class="animation-figure" src="../quick_sort.assets/pivot_division_step9.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -3737,7 +3737,7 @@
|
||||
<li>然后,对左子数组和右子数组分别递归执行“哨兵划分”。</li>
|
||||
<li>持续递归,直至子数组长度为 1 时终止,从而完成整个数组的排序。</li>
|
||||
</ol>
|
||||
<p><a class="glightbox" href="../quick_sort.assets/quick_sort_overview.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="快速排序流程" src="../quick_sort.assets/quick_sort_overview.png" /></a></p>
|
||||
<p><a class="glightbox" href="../quick_sort.assets/quick_sort_overview.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="快速排序流程" class="animation-figure" src="../quick_sort.assets/quick_sort_overview.png" /></a></p>
|
||||
<p align="center"> 图 11-9 快速排序流程 </p>
|
||||
|
||||
<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>
|
||||
|
@ -3361,7 +3361,7 @@
|
||||
<li>对学号的第 <span class="arithmatex">\(k\)</span> 位执行“计数排序”。完成后,数据会根据第 <span class="arithmatex">\(k\)</span> 位从小到大排序。</li>
|
||||
<li>将 <span class="arithmatex">\(k\)</span> 增加 <span class="arithmatex">\(1\)</span> ,然后返回步骤 <code>2.</code> 继续迭代,直到所有位都排序完成后结束。</li>
|
||||
</ol>
|
||||
<p><a class="glightbox" href="../radix_sort.assets/radix_sort_overview.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="基数排序算法流程" src="../radix_sort.assets/radix_sort_overview.png" /></a></p>
|
||||
<p><a class="glightbox" href="../radix_sort.assets/radix_sort_overview.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="基数排序算法流程" class="animation-figure" src="../radix_sort.assets/radix_sort_overview.png" /></a></p>
|
||||
<p align="center"> 图 11-18 基数排序算法流程 </p>
|
||||
|
||||
<p>下面来剖析代码实现。对于一个 <span class="arithmatex">\(d\)</span> 进制的数字 <span class="arithmatex">\(x\)</span> ,要获取其第 <span class="arithmatex">\(k\)</span> 位 <span class="arithmatex">\(x_k\)</span> ,可以使用以下计算公式:</p>
|
||||
|
@ -3350,37 +3350,37 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="1:11"><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" /><div class="tabbed-labels"><label for="__tabbed_1_1"><1></label><label for="__tabbed_1_2"><2></label><label for="__tabbed_1_3"><3></label><label for="__tabbed_1_4"><4></label><label for="__tabbed_1_5"><5></label><label for="__tabbed_1_6"><6></label><label for="__tabbed_1_7"><7></label><label for="__tabbed_1_8"><8></label><label for="__tabbed_1_9"><9></label><label for="__tabbed_1_10"><10></label><label for="__tabbed_1_11"><11></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="选择排序步骤" src="../selection_sort.assets/selection_sort_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="选择排序步骤" class="animation-figure" src="../selection_sort.assets/selection_sort_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="selection_sort_step2" src="../selection_sort.assets/selection_sort_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="selection_sort_step2" class="animation-figure" src="../selection_sort.assets/selection_sort_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="selection_sort_step3" src="../selection_sort.assets/selection_sort_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="selection_sort_step3" class="animation-figure" src="../selection_sort.assets/selection_sort_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="selection_sort_step4" src="../selection_sort.assets/selection_sort_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="selection_sort_step4" class="animation-figure" src="../selection_sort.assets/selection_sort_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="selection_sort_step5" src="../selection_sort.assets/selection_sort_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="selection_sort_step5" class="animation-figure" src="../selection_sort.assets/selection_sort_step5.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="selection_sort_step6" src="../selection_sort.assets/selection_sort_step6.png" /></a></p>
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="selection_sort_step6" class="animation-figure" src="../selection_sort.assets/selection_sort_step6.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="selection_sort_step7" src="../selection_sort.assets/selection_sort_step7.png" /></a></p>
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="selection_sort_step7" class="animation-figure" src="../selection_sort.assets/selection_sort_step7.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="selection_sort_step8" src="../selection_sort.assets/selection_sort_step8.png" /></a></p>
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="selection_sort_step8" class="animation-figure" src="../selection_sort.assets/selection_sort_step8.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="selection_sort_step9" src="../selection_sort.assets/selection_sort_step9.png" /></a></p>
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="selection_sort_step9" class="animation-figure" src="../selection_sort.assets/selection_sort_step9.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="selection_sort_step10" src="../selection_sort.assets/selection_sort_step10.png" /></a></p>
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="selection_sort_step10" class="animation-figure" src="../selection_sort.assets/selection_sort_step10.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_step11.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="selection_sort_step11" src="../selection_sort.assets/selection_sort_step11.png" /></a></p>
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_step11.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="selection_sort_step11" class="animation-figure" src="../selection_sort.assets/selection_sort_step11.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -3606,7 +3606,7 @@
|
||||
<li><strong>空间复杂度 <span class="arithmatex">\(O(1)\)</span>、原地排序</strong>:指针 <span class="arithmatex">\(i\)</span> 和 <span class="arithmatex">\(j\)</span> 使用常数大小的额外空间。</li>
|
||||
<li><strong>非稳定排序</strong>:如图 11-3 所示,元素 <code>nums[i]</code> 有可能被交换至与其相等的元素的右边,导致两者相对顺序发生改变。</li>
|
||||
</ul>
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_instability.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="选择排序非稳定示例" src="../selection_sort.assets/selection_sort_instability.png" /></a></p>
|
||||
<p><a class="glightbox" href="../selection_sort.assets/selection_sort_instability.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="选择排序非稳定示例" class="animation-figure" src="../selection_sort.assets/selection_sort_instability.png" /></a></p>
|
||||
<p align="center"> 图 11-3 选择排序非稳定示例 </p>
|
||||
|
||||
<!-- Source file information -->
|
||||
|
@ -3354,7 +3354,7 @@
|
||||
<h1 id="111">11.1 排序算法<a class="headerlink" href="#111" title="Permanent link">¶</a></h1>
|
||||
<p>「排序算法 sorting algorithm」用于对一组数据按照特定顺序进行排列。排序算法有着广泛的应用,因为有序数据通常能够被更有效地查找、分析和处理。</p>
|
||||
<p>如图 11-1 所示,排序算法中的数据类型可以是整数、浮点数、字符或字符串等。排序的判断规则可根据需求设定,如数字大小、字符 ASCII 码顺序或自定义规则。</p>
|
||||
<p><a class="glightbox" href="../sorting_algorithm.assets/sorting_examples.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="数据类型和判断规则示例" src="../sorting_algorithm.assets/sorting_examples.png" /></a></p>
|
||||
<p><a class="glightbox" href="../sorting_algorithm.assets/sorting_examples.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="数据类型和判断规则示例" class="animation-figure" src="../sorting_algorithm.assets/sorting_examples.png" /></a></p>
|
||||
<p align="center"> 图 11-1 数据类型和判断规则示例 </p>
|
||||
|
||||
<h2 id="1111">11.1.1 评价维度<a class="headerlink" href="#1111" title="Permanent link">¶</a></h2>
|
||||
|
@ -3364,7 +3364,7 @@
|
||||
<li>总的来说,我们希望找到一种排序算法,具有高效率、稳定、原地以及正向自适应性等优点。然而,正如其他数据结构和算法一样,没有一种排序算法能够同时满足所有这些条件。在实际应用中,我们需要根据数据的特性来选择合适的排序算法。</li>
|
||||
<li>图 11-19 对比了主流排序算法的效率、稳定性、就地性和自适应性等。</li>
|
||||
</ul>
|
||||
<p><a class="glightbox" href="../summary.assets/sorting_algorithms_comparison.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="排序算法对比" src="../summary.assets/sorting_algorithms_comparison.png" /></a></p>
|
||||
<p><a class="glightbox" href="../summary.assets/sorting_algorithms_comparison.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="排序算法对比" class="animation-figure" src="../summary.assets/sorting_algorithms_comparison.png" /></a></p>
|
||||
<p align="center"> 图 11-19 排序算法对比 </p>
|
||||
|
||||
<h3 id="2-q-a">2. Q & A<a class="headerlink" href="#2-q-a" title="Permanent link">¶</a></h3>
|
||||
|
@ -3407,7 +3407,7 @@
|
||||
<!-- Page content -->
|
||||
<h1 id="53">5.3 双向队列<a class="headerlink" href="#53" title="Permanent link">¶</a></h1>
|
||||
<p>在队列中,我们仅能在头部删除或在尾部添加元素。如图 5-7 所示,「双向队列 double-ended queue」提供了更高的灵活性,允许在头部和尾部执行元素的添加或删除操作。</p>
|
||||
<p><a class="glightbox" href="../deque.assets/deque_operations.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="双向队列的操作" src="../deque.assets/deque_operations.png" /></a></p>
|
||||
<p><a class="glightbox" href="../deque.assets/deque_operations.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="双向队列的操作" class="animation-figure" src="../deque.assets/deque_operations.png" /></a></p>
|
||||
<p align="center"> 图 5-7 双向队列的操作 </p>
|
||||
|
||||
<h2 id="531">5.3.1 双向队列常用操作<a class="headerlink" href="#531" title="Permanent link">¶</a></h2>
|
||||
@ -3768,19 +3768,19 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="2:5"><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" /><div class="tabbed-labels"><label for="__tabbed_2_1">LinkedListDeque</label><label for="__tabbed_2_2">pushLast()</label><label for="__tabbed_2_3">pushFirst()</label><label for="__tabbed_2_4">popLast()</label><label for="__tabbed_2_5">popFirst()</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../deque.assets/linkedlist_deque.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="基于链表实现双向队列的入队出队操作" src="../deque.assets/linkedlist_deque.png" /></a></p>
|
||||
<p><a class="glightbox" href="../deque.assets/linkedlist_deque.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="基于链表实现双向队列的入队出队操作" class="animation-figure" src="../deque.assets/linkedlist_deque.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../deque.assets/linkedlist_deque_push_last.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="linkedlist_deque_push_last" src="../deque.assets/linkedlist_deque_push_last.png" /></a></p>
|
||||
<p><a class="glightbox" href="../deque.assets/linkedlist_deque_push_last.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="linkedlist_deque_push_last" class="animation-figure" src="../deque.assets/linkedlist_deque_push_last.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../deque.assets/linkedlist_deque_push_first.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="linkedlist_deque_push_first" src="../deque.assets/linkedlist_deque_push_first.png" /></a></p>
|
||||
<p><a class="glightbox" href="../deque.assets/linkedlist_deque_push_first.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="linkedlist_deque_push_first" class="animation-figure" src="../deque.assets/linkedlist_deque_push_first.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../deque.assets/linkedlist_deque_pop_last.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="linkedlist_deque_pop_last" src="../deque.assets/linkedlist_deque_pop_last.png" /></a></p>
|
||||
<p><a class="glightbox" href="../deque.assets/linkedlist_deque_pop_last.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="linkedlist_deque_pop_last" class="animation-figure" src="../deque.assets/linkedlist_deque_pop_last.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../deque.assets/linkedlist_deque_pop_first.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="linkedlist_deque_pop_first" src="../deque.assets/linkedlist_deque_pop_first.png" /></a></p>
|
||||
<p><a class="glightbox" href="../deque.assets/linkedlist_deque_pop_first.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="linkedlist_deque_pop_first" class="animation-figure" src="../deque.assets/linkedlist_deque_pop_first.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -5392,19 +5392,19 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="4:5"><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" /><div class="tabbed-labels"><label for="__tabbed_4_1">ArrayDeque</label><label for="__tabbed_4_2">pushLast()</label><label for="__tabbed_4_3">pushFirst()</label><label for="__tabbed_4_4">popLast()</label><label for="__tabbed_4_5">popFirst()</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../deque.assets/array_deque.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="基于数组实现双向队列的入队出队操作" src="../deque.assets/array_deque.png" /></a></p>
|
||||
<p><a class="glightbox" href="../deque.assets/array_deque.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="基于数组实现双向队列的入队出队操作" class="animation-figure" src="../deque.assets/array_deque.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../deque.assets/array_deque_push_last.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="array_deque_push_last" src="../deque.assets/array_deque_push_last.png" /></a></p>
|
||||
<p><a class="glightbox" href="../deque.assets/array_deque_push_last.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="array_deque_push_last" class="animation-figure" src="../deque.assets/array_deque_push_last.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../deque.assets/array_deque_push_first.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="array_deque_push_first" src="../deque.assets/array_deque_push_first.png" /></a></p>
|
||||
<p><a class="glightbox" href="../deque.assets/array_deque_push_first.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="array_deque_push_first" class="animation-figure" src="../deque.assets/array_deque_push_first.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../deque.assets/array_deque_pop_last.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="array_deque_pop_last" src="../deque.assets/array_deque_pop_last.png" /></a></p>
|
||||
<p><a class="glightbox" href="../deque.assets/array_deque_pop_last.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="array_deque_pop_last" class="animation-figure" src="../deque.assets/array_deque_pop_last.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../deque.assets/array_deque_pop_first.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="array_deque_pop_first" src="../deque.assets/array_deque_pop_first.png" /></a></p>
|
||||
<p><a class="glightbox" href="../deque.assets/array_deque_pop_first.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="array_deque_pop_first" class="animation-figure" src="../deque.assets/array_deque_pop_first.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3292,7 +3292,7 @@
|
||||
<!-- Page content -->
|
||||
<h1 id="5">第 5 章 栈与队列<a class="headerlink" href="#5" title="Permanent link">¶</a></h1>
|
||||
<div class="center-table">
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_stack_and_queue.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="栈与队列" src="../assets/covers/chapter_stack_and_queue.jpg" width="600" /></a></p>
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_stack_and_queue.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="栈与队列" class="cover-image" src="../assets/covers/chapter_stack_and_queue.jpg" /></a></p>
|
||||
</div>
|
||||
<div class="admonition abstract">
|
||||
<p class="admonition-title">Abstract</p>
|
||||
|
@ -3408,7 +3408,7 @@
|
||||
<h1 id="52">5.2 队列<a class="headerlink" href="#52" title="Permanent link">¶</a></h1>
|
||||
<p>「队列 queue」是一种遵循先入先出规则的线性数据结构。顾名思义,队列模拟了排队现象,即新来的人不断加入队列的尾部,而位于队列头部的人逐个离开。</p>
|
||||
<p>如图 5-4 所示,我们将队列的头部称为“队首”,尾部称为“队尾”,将把元素加入队尾的操作称为“入队”,删除队首元素的操作称为“出队”。</p>
|
||||
<p><a class="glightbox" href="../queue.assets/queue_operations.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="队列的先入先出规则" src="../queue.assets/queue_operations.png" /></a></p>
|
||||
<p><a class="glightbox" href="../queue.assets/queue_operations.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="队列的先入先出规则" class="animation-figure" src="../queue.assets/queue_operations.png" /></a></p>
|
||||
<p align="center"> 图 5-4 队列的先入先出规则 </p>
|
||||
|
||||
<h2 id="521">5.2.1 队列常用操作<a class="headerlink" href="#521" title="Permanent link">¶</a></h2>
|
||||
@ -3717,13 +3717,13 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="2:3"><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" /><div class="tabbed-labels"><label for="__tabbed_2_1">LinkedListQueue</label><label for="__tabbed_2_2">push()</label><label for="__tabbed_2_3">pop()</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../queue.assets/linkedlist_queue.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="基于链表实现队列的入队出队操作" src="../queue.assets/linkedlist_queue.png" /></a></p>
|
||||
<p><a class="glightbox" href="../queue.assets/linkedlist_queue.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="基于链表实现队列的入队出队操作" class="animation-figure" src="../queue.assets/linkedlist_queue.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../queue.assets/linkedlist_queue_push.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="linkedlist_queue_push" src="../queue.assets/linkedlist_queue_push.png" /></a></p>
|
||||
<p><a class="glightbox" href="../queue.assets/linkedlist_queue_push.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="linkedlist_queue_push" class="animation-figure" src="../queue.assets/linkedlist_queue_push.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../queue.assets/linkedlist_queue_pop.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="linkedlist_queue_pop" src="../queue.assets/linkedlist_queue_pop.png" /></a></p>
|
||||
<p><a class="glightbox" href="../queue.assets/linkedlist_queue_pop.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="linkedlist_queue_pop" class="animation-figure" src="../queue.assets/linkedlist_queue_pop.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -4587,13 +4587,13 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="4:3"><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" /><div class="tabbed-labels"><label for="__tabbed_4_1">ArrayQueue</label><label for="__tabbed_4_2">push()</label><label for="__tabbed_4_3">pop()</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../queue.assets/array_queue.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="基于数组实现队列的入队出队操作" src="../queue.assets/array_queue.png" /></a></p>
|
||||
<p><a class="glightbox" href="../queue.assets/array_queue.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="基于数组实现队列的入队出队操作" class="animation-figure" src="../queue.assets/array_queue.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../queue.assets/array_queue_push.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="array_queue_push" src="../queue.assets/array_queue_push.png" /></a></p>
|
||||
<p><a class="glightbox" href="../queue.assets/array_queue_push.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="array_queue_push" class="animation-figure" src="../queue.assets/array_queue_push.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../queue.assets/array_queue_pop.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="array_queue_pop" src="../queue.assets/array_queue_pop.png" /></a></p>
|
||||
<p><a class="glightbox" href="../queue.assets/array_queue_pop.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="array_queue_pop" class="animation-figure" src="../queue.assets/array_queue_pop.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3423,7 +3423,7 @@
|
||||
<p>「栈 stack」是一种遵循先入后出的逻辑的线性数据结构。</p>
|
||||
<p>我们可以将栈类比为桌面上的一摞盘子,如果需要拿出底部的盘子,则需要先将上面的盘子依次取出。我们将盘子替换为各种类型的元素(如整数、字符、对象等),就得到了栈数据结构。</p>
|
||||
<p>如图 5-1 所示,我们把堆叠元素的顶部称为“栈顶”,底部称为“栈底”。将把元素添加到栈顶的操作叫做“入栈”,删除栈顶元素的操作叫做“出栈”。</p>
|
||||
<p><a class="glightbox" href="../stack.assets/stack_operations.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="栈的先入后出规则" src="../stack.assets/stack_operations.png" /></a></p>
|
||||
<p><a class="glightbox" href="../stack.assets/stack_operations.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="栈的先入后出规则" class="animation-figure" src="../stack.assets/stack_operations.png" /></a></p>
|
||||
<p align="center"> 图 5-1 栈的先入后出规则 </p>
|
||||
|
||||
<h2 id="511">5.1.1 栈常用操作<a class="headerlink" href="#511" title="Permanent link">¶</a></h2>
|
||||
@ -3728,13 +3728,13 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="2:3"><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" /><div class="tabbed-labels"><label for="__tabbed_2_1">LinkedListStack</label><label for="__tabbed_2_2">push()</label><label for="__tabbed_2_3">pop()</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../stack.assets/linkedlist_stack.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="基于链表实现栈的入栈出栈操作" src="../stack.assets/linkedlist_stack.png" /></a></p>
|
||||
<p><a class="glightbox" href="../stack.assets/linkedlist_stack.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="基于链表实现栈的入栈出栈操作" class="animation-figure" src="../stack.assets/linkedlist_stack.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../stack.assets/linkedlist_stack_push.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="linkedlist_stack_push" src="../stack.assets/linkedlist_stack_push.png" /></a></p>
|
||||
<p><a class="glightbox" href="../stack.assets/linkedlist_stack_push.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="linkedlist_stack_push" class="animation-figure" src="../stack.assets/linkedlist_stack_push.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../stack.assets/linkedlist_stack_pop.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="linkedlist_stack_pop" src="../stack.assets/linkedlist_stack_pop.png" /></a></p>
|
||||
<p><a class="glightbox" href="../stack.assets/linkedlist_stack_pop.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="linkedlist_stack_pop" class="animation-figure" src="../stack.assets/linkedlist_stack_pop.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -4473,13 +4473,13 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="4:3"><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" /><div class="tabbed-labels"><label for="__tabbed_4_1">ArrayStack</label><label for="__tabbed_4_2">push()</label><label for="__tabbed_4_3">pop()</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../stack.assets/array_stack.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="基于数组实现栈的入栈出栈操作" src="../stack.assets/array_stack.png" /></a></p>
|
||||
<p><a class="glightbox" href="../stack.assets/array_stack.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="基于数组实现栈的入栈出栈操作" class="animation-figure" src="../stack.assets/array_stack.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../stack.assets/array_stack_push.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="array_stack_push" src="../stack.assets/array_stack_push.png" /></a></p>
|
||||
<p><a class="glightbox" href="../stack.assets/array_stack_push.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="array_stack_push" class="animation-figure" src="../stack.assets/array_stack_push.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../stack.assets/array_stack_pop.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="array_stack_pop" src="../stack.assets/array_stack_pop.png" /></a></p>
|
||||
<p><a class="glightbox" href="../stack.assets/array_stack_pop.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="array_stack_pop" class="animation-figure" src="../stack.assets/array_stack_pop.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3371,14 +3371,14 @@
|
||||
<h2 id="731">7.3.1 表示完美二叉树<a class="headerlink" href="#731" title="Permanent link">¶</a></h2>
|
||||
<p>先分析一个简单案例。给定一个完美二叉树,我们将所有节点按照层序遍历的顺序存储在一个数组中,则每个节点都对应唯一的数组索引。</p>
|
||||
<p>根据层序遍历的特性,我们可以推导出父节点索引与子节点索引之间的“映射公式”:<strong>若节点的索引为 <span class="arithmatex">\(i\)</span> ,则该节点的左子节点索引为 <span class="arithmatex">\(2i + 1\)</span> ,右子节点索引为 <span class="arithmatex">\(2i + 2\)</span></strong> 。图 7-12 展示了各个节点索引之间的映射关系。</p>
|
||||
<p><a class="glightbox" href="../array_representation_of_tree.assets/array_representation_binary_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="完美二叉树的数组表示" src="../array_representation_of_tree.assets/array_representation_binary_tree.png" /></a></p>
|
||||
<p><a class="glightbox" href="../array_representation_of_tree.assets/array_representation_binary_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="完美二叉树的数组表示" class="animation-figure" src="../array_representation_of_tree.assets/array_representation_binary_tree.png" /></a></p>
|
||||
<p align="center"> 图 7-12 完美二叉树的数组表示 </p>
|
||||
|
||||
<p><strong>映射公式的角色相当于链表中的指针</strong>。给定数组中的任意一个节点,我们都可以通过映射公式来访问它的左(右)子节点。</p>
|
||||
<h2 id="732">7.3.2 表示任意二叉树<a class="headerlink" href="#732" title="Permanent link">¶</a></h2>
|
||||
<p>完美二叉树是一个特例,在二叉树的中间层通常存在许多 <span class="arithmatex">\(\text{None}\)</span> 。由于层序遍历序列并不包含这些 <span class="arithmatex">\(\text{None}\)</span> ,因此我们无法仅凭该序列来推测 <span class="arithmatex">\(\text{None}\)</span> 的数量和分布位置。<strong>这意味着存在多种二叉树结构都符合该层序遍历序列</strong>。</p>
|
||||
<p>如图 7-13 所示,给定一个非完美二叉树,上述的数组表示方法已经失效。</p>
|
||||
<p><a class="glightbox" href="../array_representation_of_tree.assets/array_representation_without_empty.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="层序遍历序列对应多种二叉树可能性" src="../array_representation_of_tree.assets/array_representation_without_empty.png" /></a></p>
|
||||
<p><a class="glightbox" href="../array_representation_of_tree.assets/array_representation_without_empty.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="层序遍历序列对应多种二叉树可能性" class="animation-figure" src="../array_representation_of_tree.assets/array_representation_without_empty.png" /></a></p>
|
||||
<p align="center"> 图 7-13 层序遍历序列对应多种二叉树可能性 </p>
|
||||
|
||||
<p>为了解决此问题,<strong>我们可以考虑在层序遍历序列中显式地写出所有 <span class="arithmatex">\(\text{None}\)</span></strong> 。如图 7-14 所示,这样处理后,层序遍历序列就可以唯一表示二叉树了。</p>
|
||||
@ -3456,12 +3456,12 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p><a class="glightbox" href="../array_representation_of_tree.assets/array_representation_with_empty.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="任意类型二叉树的数组表示" src="../array_representation_of_tree.assets/array_representation_with_empty.png" /></a></p>
|
||||
<p><a class="glightbox" href="../array_representation_of_tree.assets/array_representation_with_empty.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="任意类型二叉树的数组表示" class="animation-figure" src="../array_representation_of_tree.assets/array_representation_with_empty.png" /></a></p>
|
||||
<p align="center"> 图 7-14 任意类型二叉树的数组表示 </p>
|
||||
|
||||
<p>值得说明的是,<strong>完全二叉树非常适合使用数组来表示</strong>。回顾完全二叉树的定义,<span class="arithmatex">\(\text{None}\)</span> 只出现在最底层且靠右的位置,<strong>因此所有 <span class="arithmatex">\(\text{None}\)</span> 一定出现在层序遍历序列的末尾</strong>。</p>
|
||||
<p>这意味着使用数组表示完全二叉树时,可以省略存储所有 <span class="arithmatex">\(\text{None}\)</span> ,非常方便。图 7-15 给出了一个例子。</p>
|
||||
<p><a class="glightbox" href="../array_representation_of_tree.assets/array_representation_complete_binary_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="完全二叉树的数组表示" src="../array_representation_of_tree.assets/array_representation_complete_binary_tree.png" /></a></p>
|
||||
<p><a class="glightbox" href="../array_representation_of_tree.assets/array_representation_complete_binary_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="完全二叉树的数组表示" class="animation-figure" src="../array_representation_of_tree.assets/array_representation_complete_binary_tree.png" /></a></p>
|
||||
<p align="center"> 图 7-15 完全二叉树的数组表示 </p>
|
||||
|
||||
<p>以下代码实现了一个基于数组表示的二叉树,包括以下几种操作。</p>
|
||||
|
@ -3558,11 +3558,11 @@
|
||||
<h1 id="75-avl">7.5 AVL 树 *<a class="headerlink" href="#75-avl" title="Permanent link">¶</a></h1>
|
||||
<p>在二叉搜索树章节中,我们提到了在多次插入和删除操作后,二叉搜索树可能退化为链表。这种情况下,所有操作的时间复杂度将从 <span class="arithmatex">\(O(\log n)\)</span> 恶化为 <span class="arithmatex">\(O(n)\)</span> 。</p>
|
||||
<p>如图 7-24 所示,经过两次删除节点操作,这个二叉搜索树便会退化为链表。</p>
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_degradation_from_removing_node.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="AVL 树在删除节点后发生退化" src="../avl_tree.assets/avltree_degradation_from_removing_node.png" /></a></p>
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_degradation_from_removing_node.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="AVL 树在删除节点后发生退化" class="animation-figure" src="../avl_tree.assets/avltree_degradation_from_removing_node.png" /></a></p>
|
||||
<p align="center"> 图 7-24 AVL 树在删除节点后发生退化 </p>
|
||||
|
||||
<p>再例如,在图 7-25 的完美二叉树中插入两个节点后,树将严重向左倾斜,查找操作的时间复杂度也随之恶化。</p>
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_degradation_from_inserting_node.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="AVL 树在插入节点后发生退化" src="../avl_tree.assets/avltree_degradation_from_inserting_node.png" /></a></p>
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_degradation_from_inserting_node.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="AVL 树在插入节点后发生退化" class="animation-figure" src="../avl_tree.assets/avltree_degradation_from_inserting_node.png" /></a></p>
|
||||
<p align="center"> 图 7-25 AVL 树在插入节点后发生退化 </p>
|
||||
|
||||
<p>G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorithm for the organization of information" 中提出了「AVL 树」。论文中详细描述了一系列操作,确保在持续添加和删除节点后,AVL 树不会退化,从而使得各种操作的时间复杂度保持在 <span class="arithmatex">\(O(\log n)\)</span> 级别。换句话说,在需要频繁进行增删查改操作的场景中,AVL 树能始终保持高效的数据操作性能,具有很好的应用价值。</p>
|
||||
@ -4086,23 +4086,23 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="4:4"><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" /><div class="tabbed-labels"><label for="__tabbed_4_1"><1></label><label for="__tabbed_4_2"><2></label><label for="__tabbed_4_3"><3></label><label for="__tabbed_4_4"><4></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_right_rotate_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="右旋操作步骤" src="../avl_tree.assets/avltree_right_rotate_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_right_rotate_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="右旋操作步骤" class="animation-figure" src="../avl_tree.assets/avltree_right_rotate_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_right_rotate_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="avltree_right_rotate_step2" src="../avl_tree.assets/avltree_right_rotate_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_right_rotate_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="avltree_right_rotate_step2" class="animation-figure" src="../avl_tree.assets/avltree_right_rotate_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_right_rotate_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="avltree_right_rotate_step3" src="../avl_tree.assets/avltree_right_rotate_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_right_rotate_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="avltree_right_rotate_step3" class="animation-figure" src="../avl_tree.assets/avltree_right_rotate_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_right_rotate_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="avltree_right_rotate_step4" src="../avl_tree.assets/avltree_right_rotate_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_right_rotate_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="avltree_right_rotate_step4" class="animation-figure" src="../avl_tree.assets/avltree_right_rotate_step4.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p align="center"> 图 7-26 右旋操作步骤 </p>
|
||||
|
||||
<p>如图 7-27 所示,当节点 <code>child</code> 有右子节点(记为 <code>grandChild</code> )时,需要在右旋中添加一步:将 <code>grandChild</code> 作为 <code>node</code> 的左子节点。</p>
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_right_rotate_with_grandchild.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="有 grandChild 的右旋操作" src="../avl_tree.assets/avltree_right_rotate_with_grandchild.png" /></a></p>
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_right_rotate_with_grandchild.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="有 grandChild 的右旋操作" class="animation-figure" src="../avl_tree.assets/avltree_right_rotate_with_grandchild.png" /></a></p>
|
||||
<p align="center"> 图 7-27 有 grandChild 的右旋操作 </p>
|
||||
|
||||
<p>“向右旋转”是一种形象化的说法,实际上需要通过修改节点指针来实现,代码如下所示。</p>
|
||||
@ -4309,11 +4309,11 @@
|
||||
</div>
|
||||
<h3 id="2_1">2. 左旋<a class="headerlink" href="#2_1" title="Permanent link">¶</a></h3>
|
||||
<p>相应的,如果考虑上述失衡二叉树的“镜像”,则需要执行图 7-28 所示的“左旋”操作。</p>
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_left_rotate.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="左旋操作" src="../avl_tree.assets/avltree_left_rotate.png" /></a></p>
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_left_rotate.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="左旋操作" class="animation-figure" src="../avl_tree.assets/avltree_left_rotate.png" /></a></p>
|
||||
<p align="center"> 图 7-28 左旋操作 </p>
|
||||
|
||||
<p>同理,如图 7-29 所示,当节点 <code>child</code> 有左子节点(记为 <code>grandChild</code> )时,需要在左旋中添加一步:将 <code>grandChild</code> 作为 <code>node</code> 的右子节点。</p>
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_left_rotate_with_grandchild.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="有 grandChild 的左旋操作" src="../avl_tree.assets/avltree_left_rotate_with_grandchild.png" /></a></p>
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_left_rotate_with_grandchild.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="有 grandChild 的左旋操作" class="animation-figure" src="../avl_tree.assets/avltree_left_rotate_with_grandchild.png" /></a></p>
|
||||
<p align="center"> 图 7-29 有 grandChild 的左旋操作 </p>
|
||||
|
||||
<p>可以观察到,<strong>右旋和左旋操作在逻辑上是镜像对称的,它们分别解决的两种失衡情况也是对称的</strong>。基于对称性,我们只需将右旋的实现代码中的所有的 <code>left</code> 替换为 <code>right</code> ,将所有的 <code>right</code> 替换为 <code>left</code> ,即可得到左旋的实现代码。</p>
|
||||
@ -4520,17 +4520,17 @@
|
||||
</div>
|
||||
<h3 id="3">3. 先左旋后右旋<a class="headerlink" href="#3" title="Permanent link">¶</a></h3>
|
||||
<p>对于图 7-30 中的失衡节点 3 ,仅使用左旋或右旋都无法使子树恢复平衡。此时需要先对 <code>child</code> 执行“左旋”,再对 <code>node</code> 执行“右旋”。</p>
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_left_right_rotate.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="先左旋后右旋" src="../avl_tree.assets/avltree_left_right_rotate.png" /></a></p>
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_left_right_rotate.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="先左旋后右旋" class="animation-figure" src="../avl_tree.assets/avltree_left_right_rotate.png" /></a></p>
|
||||
<p align="center"> 图 7-30 先左旋后右旋 </p>
|
||||
|
||||
<h3 id="4">4. 先右旋后左旋<a class="headerlink" href="#4" title="Permanent link">¶</a></h3>
|
||||
<p>如图 7-31 所示,对于上述失衡二叉树的镜像情况,需要先对 <code>child</code> 执行“右旋”,然后对 <code>node</code> 执行“左旋”。</p>
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_right_left_rotate.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="先右旋后左旋" src="../avl_tree.assets/avltree_right_left_rotate.png" /></a></p>
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_right_left_rotate.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="先右旋后左旋" class="animation-figure" src="../avl_tree.assets/avltree_right_left_rotate.png" /></a></p>
|
||||
<p align="center"> 图 7-31 先右旋后左旋 </p>
|
||||
|
||||
<h3 id="5">5. 旋转的选择<a class="headerlink" href="#5" title="Permanent link">¶</a></h3>
|
||||
<p>图 7-32 展示的四种失衡情况与上述案例逐个对应,分别需要采用右旋、左旋、先右后左、先左后右的旋转操作。</p>
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_rotation_cases.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="AVL 树的四种旋转情况" src="../avl_tree.assets/avltree_rotation_cases.png" /></a></p>
|
||||
<p><a class="glightbox" href="../avl_tree.assets/avltree_rotation_cases.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="AVL 树的四种旋转情况" class="animation-figure" src="../avl_tree.assets/avltree_rotation_cases.png" /></a></p>
|
||||
<p align="center"> 图 7-32 AVL 树的四种旋转情况 </p>
|
||||
|
||||
<p>如下表所示,我们通过判断失衡节点的平衡因子以及较高一侧子节点的平衡因子的正负号,来确定失衡节点属于图 7-32 中的哪种情况。</p>
|
||||
|
@ -3439,7 +3439,7 @@
|
||||
<li>对于根节点,左子树中所有节点的值 <span class="arithmatex">\(<\)</span> 根节点的值 <span class="arithmatex">\(<\)</span> 右子树中所有节点的值。</li>
|
||||
<li>任意节点的左、右子树也是二叉搜索树,即同样满足条件 <code>1.</code> 。</li>
|
||||
</ol>
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/binary_search_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二叉搜索树" src="../binary_search_tree.assets/binary_search_tree.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/binary_search_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二叉搜索树" class="animation-figure" src="../binary_search_tree.assets/binary_search_tree.png" /></a></p>
|
||||
<p align="center"> 图 7-16 二叉搜索树 </p>
|
||||
|
||||
<h2 id="741">7.4.1 二叉搜索树的操作<a class="headerlink" href="#741" title="Permanent link">¶</a></h2>
|
||||
@ -3454,16 +3454,16 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="1:4"><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" /><div class="tabbed-labels"><label for="__tabbed_1_1"><1></label><label for="__tabbed_1_2"><2></label><label for="__tabbed_1_3"><3></label><label for="__tabbed_1_4"><4></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_search_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二叉搜索树查找节点示例" src="../binary_search_tree.assets/bst_search_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_search_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二叉搜索树查找节点示例" class="animation-figure" src="../binary_search_tree.assets/bst_search_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_search_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bst_search_step2" src="../binary_search_tree.assets/bst_search_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_search_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bst_search_step2" class="animation-figure" src="../binary_search_tree.assets/bst_search_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_search_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bst_search_step3" src="../binary_search_tree.assets/bst_search_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_search_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bst_search_step3" class="animation-figure" src="../binary_search_tree.assets/bst_search_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_search_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bst_search_step4" src="../binary_search_tree.assets/bst_search_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_search_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bst_search_step4" class="animation-figure" src="../binary_search_tree.assets/bst_search_step4.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -3733,7 +3733,7 @@
|
||||
<li><strong>查找插入位置</strong>:与查找操作相似,从根节点出发,根据当前节点值和 <code>num</code> 的大小关系循环向下搜索,直到越过叶节点(遍历至 <span class="arithmatex">\(\text{None}\)</span> )时跳出循环。</li>
|
||||
<li><strong>在该位置插入节点</strong>:初始化节点 <code>num</code> ,将该节点置于 <span class="arithmatex">\(\text{None}\)</span> 的位置。</li>
|
||||
</ol>
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_insert.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="在二叉搜索树中插入节点" src="../binary_search_tree.assets/bst_insert.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_insert.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="在二叉搜索树中插入节点" class="animation-figure" src="../binary_search_tree.assets/bst_insert.png" /></a></p>
|
||||
<p align="center"> 图 7-18 在二叉搜索树中插入节点 </p>
|
||||
|
||||
<p>在代码实现中,需要注意以下两点。</p>
|
||||
@ -4134,11 +4134,11 @@
|
||||
<p>与插入节点类似,我们需要保证在删除操作完成后,二叉搜索树的“左子树 < 根节点 < 右子树”的性质仍然满足。</p>
|
||||
<p>因此,我们需要根据目标节点的子节点数量,共分为 0、1 和 2 这三种情况,执行对应的删除节点操作。</p>
|
||||
<p>如图 7-19 所示,当待删除节点的度为 <span class="arithmatex">\(0\)</span> 时,表示该节点是叶节点,可以直接删除。</p>
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_remove_case1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="在二叉搜索树中删除节点(度为 0 )" src="../binary_search_tree.assets/bst_remove_case1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_remove_case1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="在二叉搜索树中删除节点(度为 0 )" class="animation-figure" src="../binary_search_tree.assets/bst_remove_case1.png" /></a></p>
|
||||
<p align="center"> 图 7-19 在二叉搜索树中删除节点(度为 0 ) </p>
|
||||
|
||||
<p>如图 7-20 所示,当待删除节点的度为 <span class="arithmatex">\(1\)</span> 时,将待删除节点替换为其子节点即可。</p>
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_remove_case2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="在二叉搜索树中删除节点(度为 1 )" src="../binary_search_tree.assets/bst_remove_case2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_remove_case2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="在二叉搜索树中删除节点(度为 1 )" class="animation-figure" src="../binary_search_tree.assets/bst_remove_case2.png" /></a></p>
|
||||
<p align="center"> 图 7-20 在二叉搜索树中删除节点(度为 1 ) </p>
|
||||
|
||||
<p>当待删除节点的度为 <span class="arithmatex">\(2\)</span> 时,我们无法直接删除它,而需要使用一个节点替换该节点。由于要保持二叉搜索树“左 <span class="arithmatex">\(<\)</span> 根 <span class="arithmatex">\(<\)</span> 右”的性质,<strong>因此这个节点可以是右子树的最小节点或左子树的最大节点</strong>。</p>
|
||||
@ -4150,16 +4150,16 @@
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="4:4"><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" /><div class="tabbed-labels"><label for="__tabbed_4_1"><1></label><label for="__tabbed_4_2"><2></label><label for="__tabbed_4_3"><3></label><label for="__tabbed_4_4"><4></label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_remove_case3_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="在二叉搜索树中删除节点(度为 2 )" src="../binary_search_tree.assets/bst_remove_case3_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_remove_case3_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="在二叉搜索树中删除节点(度为 2 )" class="animation-figure" src="../binary_search_tree.assets/bst_remove_case3_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_remove_case3_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bst_remove_case3_step2" src="../binary_search_tree.assets/bst_remove_case3_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_remove_case3_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bst_remove_case3_step2" class="animation-figure" src="../binary_search_tree.assets/bst_remove_case3_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_remove_case3_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bst_remove_case3_step3" src="../binary_search_tree.assets/bst_remove_case3_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_remove_case3_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bst_remove_case3_step3" class="animation-figure" src="../binary_search_tree.assets/bst_remove_case3_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_remove_case3_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bst_remove_case3_step4" src="../binary_search_tree.assets/bst_remove_case3_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_remove_case3_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="bst_remove_case3_step4" class="animation-figure" src="../binary_search_tree.assets/bst_remove_case3_step4.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -4820,7 +4820,7 @@
|
||||
<p>如图 7-22 所示,二叉树的中序遍历遵循“左 <span class="arithmatex">\(\rightarrow\)</span> 根 <span class="arithmatex">\(\rightarrow\)</span> 右”的遍历顺序,而二叉搜索树满足“左子节点 <span class="arithmatex">\(<\)</span> 根节点 <span class="arithmatex">\(<\)</span> 右子节点”的大小关系。</p>
|
||||
<p>这意味着在二叉搜索树中进行中序遍历时,总是会优先遍历下一个最小节点,从而得出一个重要性质:<strong>二叉搜索树的中序遍历序列是升序的</strong>。</p>
|
||||
<p>利用中序遍历升序的性质,我们在二叉搜索树中获取有序数据仅需 <span class="arithmatex">\(O(n)\)</span> 时间,无须进行额外的排序操作,非常高效。</p>
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_inorder_traversal.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二叉搜索树的中序遍历序列" src="../binary_search_tree.assets/bst_inorder_traversal.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_inorder_traversal.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二叉搜索树的中序遍历序列" class="animation-figure" src="../binary_search_tree.assets/bst_inorder_traversal.png" /></a></p>
|
||||
<p align="center"> 图 7-22 二叉搜索树的中序遍历序列 </p>
|
||||
|
||||
<h2 id="742">7.4.2 二叉搜索树的效率<a class="headerlink" href="#742" title="Permanent link">¶</a></h2>
|
||||
@ -4857,7 +4857,7 @@
|
||||
</div>
|
||||
<p>在理想情况下,二叉搜索树是“平衡”的,这样就可以在 <span class="arithmatex">\(\log n\)</span> 轮循环内查找任意节点。</p>
|
||||
<p>然而,如果我们在二叉搜索树中不断地插入和删除节点,可能导致二叉树退化为图 7-23 所示的链表,这时各种操作的时间复杂度也会退化为 <span class="arithmatex">\(O(n)\)</span> 。</p>
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_degradation.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二叉搜索树的退化" src="../binary_search_tree.assets/bst_degradation.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_search_tree.assets/bst_degradation.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二叉搜索树的退化" class="animation-figure" src="../binary_search_tree.assets/bst_degradation.png" /></a></p>
|
||||
<p align="center"> 图 7-23 二叉搜索树的退化 </p>
|
||||
|
||||
<h2 id="743">7.4.3 二叉搜索树常见应用<a class="headerlink" href="#743" title="Permanent link">¶</a></h2>
|
||||
|
@ -3652,7 +3652,7 @@
|
||||
</div>
|
||||
<p>每个节点都有两个引用(指针),分别指向「左子节点 left-child node」和「右子节点 right-child node」,该节点被称为这两个子节点的「父节点 parent node」。当给定一个二叉树的节点时,我们将该节点的左子节点及其以下节点形成的树称为该节点的「左子树 left subtree」,同理可得「右子树 right subtree」。</p>
|
||||
<p><strong>在二叉树中,除叶节点外,其他所有节点都包含子节点和非空子树</strong>。如图 7-1 所示,如果将“节点 2”视为父节点,则其左子节点和右子节点分别是“节点 4”和“节点 5”,左子树是“节点 4 及其以下节点形成的树”,右子树是“节点 5 及其以下节点形成的树”。</p>
|
||||
<p><a class="glightbox" href="../binary_tree.assets/binary_tree_definition.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="父节点、子节点、子树" src="../binary_tree.assets/binary_tree_definition.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_tree.assets/binary_tree_definition.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="父节点、子节点、子树" class="animation-figure" src="../binary_tree.assets/binary_tree_definition.png" /></a></p>
|
||||
<p align="center"> 图 7-1 父节点、子节点、子树 </p>
|
||||
|
||||
<h2 id="711">7.1.1 二叉树常见术语<a class="headerlink" href="#711" title="Permanent link">¶</a></h2>
|
||||
@ -3667,7 +3667,7 @@
|
||||
<li>节点的「深度 depth」:从根节点到该节点所经过的边的数量。</li>
|
||||
<li>节点的「高度 height」:从距离该节点最远的叶节点到该节点所经过的边的数量。</li>
|
||||
</ul>
|
||||
<p><a class="glightbox" href="../binary_tree.assets/binary_tree_terminology.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二叉树的常用术语" src="../binary_tree.assets/binary_tree_terminology.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_tree.assets/binary_tree_terminology.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二叉树的常用术语" class="animation-figure" src="../binary_tree.assets/binary_tree_terminology.png" /></a></p>
|
||||
<p align="center"> 图 7-2 二叉树的常用术语 </p>
|
||||
|
||||
<div class="admonition tip">
|
||||
@ -3849,7 +3849,7 @@
|
||||
</div>
|
||||
<h3 id="2">2. 插入与删除节点<a class="headerlink" href="#2" title="Permanent link">¶</a></h3>
|
||||
<p>与链表类似,在二叉树中插入与删除节点可以通过修改指针来实现。图 7-3 给出了一个示例。</p>
|
||||
<p><a class="glightbox" href="../binary_tree.assets/binary_tree_add_remove.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="在二叉树中插入与删除节点" src="../binary_tree.assets/binary_tree_add_remove.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_tree.assets/binary_tree_add_remove.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="在二叉树中插入与删除节点" class="animation-figure" src="../binary_tree.assets/binary_tree_add_remove.png" /></a></p>
|
||||
<p align="center"> 图 7-3 在二叉树中插入与删除节点 </p>
|
||||
|
||||
<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>
|
||||
@ -3978,22 +3978,22 @@
|
||||
<p class="admonition-title">Tip</p>
|
||||
<p>请注意,在中文社区中,完美二叉树常被称为「满二叉树」。</p>
|
||||
</div>
|
||||
<p><a class="glightbox" href="../binary_tree.assets/perfect_binary_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="完美二叉树" src="../binary_tree.assets/perfect_binary_tree.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_tree.assets/perfect_binary_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="完美二叉树" class="animation-figure" src="../binary_tree.assets/perfect_binary_tree.png" /></a></p>
|
||||
<p align="center"> 图 7-4 完美二叉树 </p>
|
||||
|
||||
<h3 id="2_1">2. 完全二叉树<a class="headerlink" href="#2_1" title="Permanent link">¶</a></h3>
|
||||
<p>如图 7-5 所示,「完全二叉树 complete binary tree」只有最底层的节点未被填满,且最底层节点尽量靠左填充。</p>
|
||||
<p><a class="glightbox" href="../binary_tree.assets/complete_binary_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="完全二叉树" src="../binary_tree.assets/complete_binary_tree.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_tree.assets/complete_binary_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="完全二叉树" class="animation-figure" src="../binary_tree.assets/complete_binary_tree.png" /></a></p>
|
||||
<p align="center"> 图 7-5 完全二叉树 </p>
|
||||
|
||||
<h3 id="3">3. 完满二叉树<a class="headerlink" href="#3" title="Permanent link">¶</a></h3>
|
||||
<p>如图 7-6 所示,「完满二叉树 full binary tree」除了叶节点之外,其余所有节点都有两个子节点。</p>
|
||||
<p><a class="glightbox" href="../binary_tree.assets/full_binary_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="完满二叉树" src="../binary_tree.assets/full_binary_tree.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_tree.assets/full_binary_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="完满二叉树" class="animation-figure" src="../binary_tree.assets/full_binary_tree.png" /></a></p>
|
||||
<p align="center"> 图 7-6 完满二叉树 </p>
|
||||
|
||||
<h3 id="4">4. 平衡二叉树<a class="headerlink" href="#4" title="Permanent link">¶</a></h3>
|
||||
<p>如图 7-7 所示,「平衡二叉树 balanced binary tree」中任意节点的左子树和右子树的高度之差的绝对值不超过 1 。</p>
|
||||
<p><a class="glightbox" href="../binary_tree.assets/balanced_binary_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="平衡二叉树" src="../binary_tree.assets/balanced_binary_tree.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_tree.assets/balanced_binary_tree.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="平衡二叉树" class="animation-figure" src="../binary_tree.assets/balanced_binary_tree.png" /></a></p>
|
||||
<p align="center"> 图 7-7 平衡二叉树 </p>
|
||||
|
||||
<h2 id="714">7.1.4 二叉树的退化<a class="headerlink" href="#714" title="Permanent link">¶</a></h2>
|
||||
@ -4002,7 +4002,7 @@
|
||||
<li>完美二叉树是理想情况,可以充分发挥二叉树“分治”的优势。</li>
|
||||
<li>链表则是另一个极端,各项操作都变为线性操作,时间复杂度退化至 <span class="arithmatex">\(O(n)\)</span> 。</li>
|
||||
</ul>
|
||||
<p><a class="glightbox" href="../binary_tree.assets/binary_tree_best_worst_cases.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二叉树的最佳与最差结构" src="../binary_tree.assets/binary_tree_best_worst_cases.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_tree.assets/binary_tree_best_worst_cases.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二叉树的最佳与最差结构" class="animation-figure" src="../binary_tree.assets/binary_tree_best_worst_cases.png" /></a></p>
|
||||
<p align="center"> 图 7-8 二叉树的最佳与最差结构 </p>
|
||||
|
||||
<p>如表 7-1 所示,在最佳和最差结构下,二叉树的叶节点数量、节点总数、高度等达到极大或极小值。</p>
|
||||
|
@ -3437,7 +3437,7 @@
|
||||
<h2 id="721">7.2.1 层序遍历<a class="headerlink" href="#721" title="Permanent link">¶</a></h2>
|
||||
<p>如图 7-9 所示,「层序遍历 level-order traversal」从顶部到底部逐层遍历二叉树,并在每一层按照从左到右的顺序访问节点。</p>
|
||||
<p>层序遍历本质上属于「广度优先遍历 breadth-first traversal」,它体现了一种“一圈一圈向外扩展”的逐层遍历方式。</p>
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/binary_tree_bfs.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二叉树的层序遍历" src="../binary_tree_traversal.assets/binary_tree_bfs.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/binary_tree_bfs.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二叉树的层序遍历" class="animation-figure" src="../binary_tree_traversal.assets/binary_tree_bfs.png" /></a></p>
|
||||
<p align="center"> 图 7-9 二叉树的层序遍历 </p>
|
||||
|
||||
<h3 id="1">1. 代码实现<a class="headerlink" href="#1" title="Permanent link">¶</a></h3>
|
||||
@ -3732,7 +3732,7 @@
|
||||
<h2 id="722">7.2.2 前序、中序、后序遍历<a class="headerlink" href="#722" title="Permanent link">¶</a></h2>
|
||||
<p>相应地,前序、中序和后序遍历都属于「深度优先遍历 depth-first traversal」,它体现了一种“先走到尽头,再回溯继续”的遍历方式。</p>
|
||||
<p>图 7-10 展示了对二叉树进行深度优先遍历的工作原理。<strong>深度优先遍历就像是绕着整个二叉树的外围“走”一圈</strong>,在每个节点都会遇到三个位置,分别对应前序遍历、中序遍历和后序遍历。</p>
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/binary_tree_dfs.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二叉搜索树的前、中、后序遍历" src="../binary_tree_traversal.assets/binary_tree_dfs.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/binary_tree_dfs.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="二叉搜索树的前、中、后序遍历" class="animation-figure" src="../binary_tree_traversal.assets/binary_tree_dfs.png" /></a></p>
|
||||
<p align="center"> 图 7-10 二叉搜索树的前、中、后序遍历 </p>
|
||||
|
||||
<h3 id="1_1">1. 代码实现<a class="headerlink" href="#1_1" title="Permanent link">¶</a></h3>
|
||||
@ -4140,37 +4140,37 @@
|
||||
<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">
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/preorder_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="前序遍历的递归过程" src="../binary_tree_traversal.assets/preorder_step1.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/preorder_step1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="前序遍历的递归过程" class="animation-figure" src="../binary_tree_traversal.assets/preorder_step1.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/preorder_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_step2" src="../binary_tree_traversal.assets/preorder_step2.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/preorder_step2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_step2" class="animation-figure" src="../binary_tree_traversal.assets/preorder_step2.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/preorder_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_step3" src="../binary_tree_traversal.assets/preorder_step3.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/preorder_step3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_step3" class="animation-figure" src="../binary_tree_traversal.assets/preorder_step3.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/preorder_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_step4" src="../binary_tree_traversal.assets/preorder_step4.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/preorder_step4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_step4" class="animation-figure" src="../binary_tree_traversal.assets/preorder_step4.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/preorder_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_step5" src="../binary_tree_traversal.assets/preorder_step5.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/preorder_step5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_step5" class="animation-figure" src="../binary_tree_traversal.assets/preorder_step5.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/preorder_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_step6" src="../binary_tree_traversal.assets/preorder_step6.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/preorder_step6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_step6" class="animation-figure" src="../binary_tree_traversal.assets/preorder_step6.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/preorder_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_step7" src="../binary_tree_traversal.assets/preorder_step7.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/preorder_step7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_step7" class="animation-figure" src="../binary_tree_traversal.assets/preorder_step7.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/preorder_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_step8" src="../binary_tree_traversal.assets/preorder_step8.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/preorder_step8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_step8" class="animation-figure" src="../binary_tree_traversal.assets/preorder_step8.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/preorder_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_step9" src="../binary_tree_traversal.assets/preorder_step9.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/preorder_step9.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_step9" class="animation-figure" src="../binary_tree_traversal.assets/preorder_step9.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/preorder_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_step10" src="../binary_tree_traversal.assets/preorder_step10.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/preorder_step10.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_step10" class="animation-figure" src="../binary_tree_traversal.assets/preorder_step10.png" /></a></p>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/preorder_step11.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_step11" src="../binary_tree_traversal.assets/preorder_step11.png" /></a></p>
|
||||
<p><a class="glightbox" href="../binary_tree_traversal.assets/preorder_step11.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="preorder_step11" class="animation-figure" src="../binary_tree_traversal.assets/preorder_step11.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3292,7 +3292,7 @@
|
||||
<!-- Page content -->
|
||||
<h1 id="7">第 7 章 树<a class="headerlink" href="#7" title="Permanent link">¶</a></h1>
|
||||
<div class="center-table">
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_tree.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="树" src="../assets/covers/chapter_tree.jpg" width="600" /></a></p>
|
||||
<p><a class="glightbox" href="../assets/covers/chapter_tree.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="树" class="cover-image" src="../assets/covers/chapter_tree.jpg" /></a></p>
|
||||
</div>
|
||||
<div class="admonition abstract">
|
||||
<p class="admonition-title">Abstract</p>
|
||||
|
@ -3258,8 +3258,8 @@
|
||||
<h1 align="center"> </h1>
|
||||
|
||||
<p align="center">
|
||||
<img src="index.assets/conceptual_rendering.png" width="250">
|
||||
<img src="index.assets/hello_algo_mindmap_tp.png" width="400">
|
||||
<img src="index.assets/conceptual_rendering.png" width="200">
|
||||
<img src="index.assets/hello_algo_mindmap_tp.png" width="320">
|
||||
</p>
|
||||
|
||||
<h2 align="center"> 《 Hello 算法 》</h2>
|
||||
|
206
sitemap.xml
206
sitemap.xml
@ -2,517 +2,517 @@
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_appendix/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_appendix/contribution/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_appendix/installation/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_appendix/terminology/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_array_and_linkedlist/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_array_and_linkedlist/array/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_array_and_linkedlist/linked_list/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_array_and_linkedlist/list/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_array_and_linkedlist/summary/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_backtracking/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_backtracking/backtracking_algorithm/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_backtracking/n_queens_problem/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_backtracking/permutations_problem/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_backtracking/subset_sum_problem/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_backtracking/summary/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_computational_complexity/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_computational_complexity/iteration_and_recursion/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_computational_complexity/performance_evaluation/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_computational_complexity/space_complexity/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_computational_complexity/summary/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_computational_complexity/time_complexity/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_data_structure/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_data_structure/basic_data_types/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_data_structure/character_encoding/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_data_structure/classification_of_data_structure/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_data_structure/number_encoding/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_data_structure/summary/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_divide_and_conquer/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_divide_and_conquer/binary_search_recur/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_divide_and_conquer/build_binary_tree_problem/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_divide_and_conquer/divide_and_conquer/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_divide_and_conquer/hanota_problem/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_divide_and_conquer/summary/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_dynamic_programming/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_dynamic_programming/dp_problem_features/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_dynamic_programming/dp_solution_pipeline/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_dynamic_programming/edit_distance_problem/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_dynamic_programming/intro_to_dynamic_programming/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_dynamic_programming/knapsack_problem/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_dynamic_programming/summary/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_dynamic_programming/unbounded_knapsack_problem/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_graph/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_graph/graph/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_graph/graph_operations/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_graph/graph_traversal/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_graph/summary/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_greedy/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_greedy/fractional_knapsack_problem/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_greedy/greedy_algorithm/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_greedy/max_capacity_problem/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_greedy/max_product_cutting_problem/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_greedy/summary/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_hashing/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_hashing/hash_algorithm/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_hashing/hash_collision/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_hashing/hash_map/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_hashing/summary/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_heap/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_heap/build_heap/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_heap/heap/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_heap/summary/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_heap/top_k/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_introduction/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_introduction/algorithms_are_everywhere/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_introduction/summary/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_introduction/what_is_dsa/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_preface/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_preface/about_the_book/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_preface/suggestions/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_preface/summary/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_reference/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_searching/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_searching/binary_search/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_searching/binary_search_edge/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_searching/binary_search_insertion/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_searching/replace_linear_by_hashing/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_searching/searching_algorithm_revisited/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_searching/summary/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/bubble_sort/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/bucket_sort/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/counting_sort/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/heap_sort/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/insertion_sort/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/merge_sort/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/quick_sort/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/radix_sort/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/selection_sort/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/sorting_algorithm/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/summary/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_stack_and_queue/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_stack_and_queue/deque/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_stack_and_queue/queue/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_stack_and_queue/stack/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_stack_and_queue/summary/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_tree/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_tree/array_representation_of_tree/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_tree/avl_tree/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_tree/binary_search_tree/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_tree/binary_tree/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_tree/binary_tree_traversal/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_tree/summary/</loc>
|
||||
<lastmod>2023-11-07</lastmod>
|
||||
<lastmod>2023-11-08</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
</urlset>
|
BIN
sitemap.xml.gz
BIN
sitemap.xml.gz
Binary file not shown.
@ -25,7 +25,7 @@
|
||||
--md-default-fg-color: #adbac7;
|
||||
--md-default-bg-color: #22272e;
|
||||
|
||||
--md-code-bg-color: #1D2126;
|
||||
--md-code-bg-color: #1d2126;
|
||||
--md-code-fg-color: #adbac7;
|
||||
|
||||
--md-accent-fg-color: #aaa;
|
||||
@ -43,6 +43,23 @@
|
||||
color: var(--md-default-fg-color) !important;
|
||||
}
|
||||
|
||||
/* Figure class */
|
||||
.animation-figure {
|
||||
border-radius: 0.63rem;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* Cover image class */
|
||||
.cover-image {
|
||||
width: 28rem;
|
||||
height: auto;
|
||||
border-radius: 0.3rem;
|
||||
box-shadow: var(--md-shadow-z2);
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* Center Markdown Tables (requires md_in_html extension) */
|
||||
.center-table {
|
||||
text-align: center;
|
||||
@ -82,12 +99,6 @@
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/* Image align center */
|
||||
.center {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* font-family setting for Win10 */
|
||||
body {
|
||||
--md-text-font-family: -apple-system, BlinkMacSystemFont,
|
||||
|
Loading…
Reference in New Issue
Block a user