mirror of
https://github.com/krahets/hello-algo.git
synced 2026-07-13 15:56:05 +00:00
deploy
This commit is contained in:
@@ -2638,7 +2638,7 @@ x_k = \lfloor\frac{x}{d^{k-1}}\rfloor \bmod d
|
||||
<a id="__codelineno-9-11" name="__codelineno-9-11" href="#__codelineno-9-11"></a><span class="w"> </span><span class="c1">// defer mem_arena.deinit();</span>
|
||||
<a id="__codelineno-9-12" name="__codelineno-9-12" href="#__codelineno-9-12"></a><span class="w"> </span><span class="kr">const</span><span class="w"> </span><span class="n">mem_allocator</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">mem_arena</span><span class="p">.</span><span class="n">allocator</span><span class="p">();</span>
|
||||
<a id="__codelineno-9-13" name="__codelineno-9-13" href="#__codelineno-9-13"></a><span class="w"> </span><span class="kr">var</span><span class="w"> </span><span class="n">counter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">try</span><span class="w"> </span><span class="n">mem_allocator</span><span class="p">.</span><span class="n">alloc</span><span class="p">(</span><span class="kt">usize</span><span class="p">,</span><span class="w"> </span><span class="mi">10</span><span class="p">);</span>
|
||||
<a id="__codelineno-9-14" name="__codelineno-9-14" href="#__codelineno-9-14"></a><span class="w"> </span><span class="n">std</span><span class="p">.</span><span class="n">mem</span><span class="p">.</span><span class="n">set</span><span class="p">(</span><span class="kt">usize</span><span class="p">,</span><span class="w"> </span><span class="n">counter</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
|
||||
<a id="__codelineno-9-14" name="__codelineno-9-14" href="#__codelineno-9-14"></a><span class="w"> </span><span class="nb">@memset</span><span class="p">(</span><span class="n">counter</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
|
||||
<a id="__codelineno-9-15" name="__codelineno-9-15" href="#__codelineno-9-15"></a><span class="w"> </span><span class="kr">var</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">nums</span><span class="p">.</span><span class="n">len</span><span class="p">;</span>
|
||||
<a id="__codelineno-9-16" name="__codelineno-9-16" href="#__codelineno-9-16"></a><span class="w"> </span><span class="c1">// 统计 0~9 各数字的出现次数</span>
|
||||
<a id="__codelineno-9-17" name="__codelineno-9-17" href="#__codelineno-9-17"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">nums</span><span class="p">)</span><span class="w"> </span><span class="o">|</span><span class="n">num</span><span class="o">|</span><span class="w"> </span><span class="p">{</span>
|
||||
|
||||
@@ -2136,12 +2136,27 @@
|
||||
</ul>
|
||||
<h2 id="11111-q-a">11.11.1. Q & A<a class="headerlink" href="#11111-q-a" title="Permanent link">¶</a></h2>
|
||||
<div class="admonition question">
|
||||
<p class="admonition-title">排序算法稳定性在什么情况下是必须的?</p>
|
||||
<p>在现实中,我们有可能是在对象的某个属性上进行排序。例如,学生有姓名和身高两个属性,我们希望实现一个多级排序/</p>
|
||||
<p>先按照姓名进行排序,得到 <code>(A, 180) (B, 185) (C, 170) (D, 170)</code> ;接下来对身高进行排序。由于排序算法不稳定,我们可能得到 <code>(D, 170) (C, 170) (A, 180) (B, 185)</code> 。</p>
|
||||
<p>可以发现,学生 D 和 C 的位置发生了交换,姓名的有序性被破坏了,而这是我们不希望看到的。</p>
|
||||
</div>
|
||||
<div class="admonition question">
|
||||
<p class="admonition-title">哨兵划分中“从右往左查找”与“从左往右查找”的顺序可以交换吗?</p>
|
||||
<p>不行,当我们以最左端元素为基准数时,必须先“从右往左查找”再“从左往右查找”。这个结论有些反直觉,我们来剖析一下原因。</p>
|
||||
<p>哨兵划分 <code>partition()</code> 的最后一步是交换 <code>nums[left]</code> 和 <code>nums[i]</code> 。完成交换后,基准数左边的元素都 <code><=</code> 基准数,<strong>这就要求最后一步交换前 <code>nums[left] >= nums[i]</code> 必须成立</strong>。假设我们先“从左往右查找”,那么如果找不到比基准数更小的元素,<strong>则会在 <code>i == j</code> 时跳出循环,此时可能 <code>nums[j] == nums[i] > nums[left]</code></strong>。也就是说,此时最后一步交换操作会把一个比基准数更大的元素交换至数组最左端,导致哨兵划分失败。</p>
|
||||
<p>举个例子,给定数组 <code>[0, 0, 0, 0, 1]</code> ,如果先“从左向右查找”,哨兵划分后数组为 <code>[1, 0, 0, 0, 0]</code> ,这个结果是不正确的。</p>
|
||||
<p>再深入思考一下,如果我们选择 <code>nums[right]</code> 为基准数,那么正好反过来,必须先“从左往右查找”。</p>
|
||||
</div>
|
||||
<div class="admonition question">
|
||||
<p class="admonition-title">关于尾递归优化,为什么选短的数组能保证递归深度不超过 <span class="arithmatex">\(log n\)</span> ?</p>
|
||||
<p>递归深度就是当前未返回的递归方法的数量。每轮哨兵划分我们将原数组划分为两个子数组。在尾递归优化后,向下递归的子数组长度最大为原数组的一半长度。假设最差情况,一直为一半长度,那么最终的递归深度就是 <span class="arithmatex">\(log n\)</span> 。</p>
|
||||
<p>回顾原始的快速排序,我们有可能会连续地递归长度较大的数组,最差情况下为 <span class="arithmatex">\(n, n - 1, n - 2, ..., 2, 1\)</span> ,从而递归深度为 <span class="arithmatex">\(n\)</span> 。尾递归优化可以避免这种情况的出现。</p>
|
||||
</div>
|
||||
<div class="admonition question">
|
||||
<p class="admonition-title">桶排序的最差时间复杂度为什么是 <span class="arithmatex">\(O(n^2)\)</span> ?</p>
|
||||
<p>最差情况下,所有元素被分至同一个桶中。如果我们采用一个 <span class="arithmatex">\(O(n^2)\)</span> 算法来排序这些元素,则时间复杂度为 <span class="arithmatex">\(O(n^2)\)</span> 。</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user