mirror of
https://github.com/krahets/hello-algo.git
synced 2026-08-27 18:37:13 +00:00
deploy
This commit is contained in:
@@ -3435,17 +3435,17 @@
|
||||
<p>我们可以进行 <span class="arithmatex">\(k\)</span> 轮遍历,分别在每轮中提取第 <span class="arithmatex">\(1\)</span> , <span class="arithmatex">\(2\)</span> , <span class="arithmatex">\(\cdots\)</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><img alt="遍历寻找最大的 k 个元素" src="../top_k.assets/top_k_traversal.png" /></p>
|
||||
<p align="center"> Fig. 遍历寻找最大的 k 个元素 </p>
|
||||
<p align="center"> 图:遍历寻找最大的 k 个元素 </p>
|
||||
|
||||
<div class="admonition tip">
|
||||
<p class="admonition-title">Tip</p>
|
||||
<p>当 <span class="arithmatex">\(k = n\)</span> 时,我们可以得到从大到小的序列,等价于「选择排序」算法。 </p>
|
||||
<p>当 <span class="arithmatex">\(k = n\)</span> 时,我们可以得到从大到小的序列,等价于「选择排序」算法。</p>
|
||||
</div>
|
||||
<h2 id="832">8.3.2. 方法二:排序<a class="headerlink" href="#832" title="Permanent link">¶</a></h2>
|
||||
<p>我们可以对数组 <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><img alt="排序寻找最大的 k 个元素" src="../top_k.assets/top_k_sorting.png" /></p>
|
||||
<p align="center"> Fig. 排序寻找最大的 k 个元素 </p>
|
||||
<p align="center"> 图:排序寻找最大的 k 个元素 </p>
|
||||
|
||||
<h2 id="833">8.3.3. 方法三:堆<a class="headerlink" href="#833" title="Permanent link">¶</a></h2>
|
||||
<p>我们可以基于堆更加高效地解决 Top-K 问题,流程如下:</p>
|
||||
@@ -3486,6 +3486,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p align="center"> 图:基于堆寻找最大的 k 个元素 </p>
|
||||
|
||||
<p>总共执行了 <span class="arithmatex">\(n\)</span> 轮入堆和出堆,堆的最大长度为 <span class="arithmatex">\(k\)</span> ,因此时间复杂度为 <span class="arithmatex">\(O(n \log k)\)</span> 。该方法的效率很高,当 <span class="arithmatex">\(k\)</span> 较小时,时间复杂度趋向 <span class="arithmatex">\(O(n)\)</span> ;当 <span class="arithmatex">\(k\)</span> 较大时,时间复杂度不会超过 <span class="arithmatex">\(O(n \log n)\)</span> 。</p>
|
||||
<p>另外,该方法适用于动态数据流的使用场景。在不断加入数据时,我们可以持续维护堆内的元素,从而实现最大 <span class="arithmatex">\(k\)</span> 个元素的动态更新。</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">Java</label><label for="__tabbed_2_2">C++</label><label for="__tabbed_2_3">Python</label><label for="__tabbed_2_4">Go</label><label for="__tabbed_2_5">JS</label><label for="__tabbed_2_6">TS</label><label for="__tabbed_2_7">C</label><label for="__tabbed_2_8">C#</label><label for="__tabbed_2_9">Swift</label><label for="__tabbed_2_10">Zig</label><label for="__tabbed_2_11">Dart</label><label for="__tabbed_2_12">Rust</label></div>
|
||||
@@ -3621,7 +3623,20 @@
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<div class="highlight"><span class="filename">top_k.dart</span><pre><span></span><code><a id="__codelineno-10-1" name="__codelineno-10-1" href="#__codelineno-10-1"></a><span class="p">[</span><span class="n">class</span><span class="p">]{}</span><span class="o">-</span><span class="p">[</span><span class="n">func</span><span class="p">]{</span><span class="n">top_k_heap</span><span class="p">}</span>
|
||||
<div class="highlight"><span class="filename">top_k.dart</span><pre><span></span><code><a id="__codelineno-10-1" name="__codelineno-10-1" href="#__codelineno-10-1"></a><span class="cm">/* 基于堆查找数组中最大的 k 个元素 */</span>
|
||||
<a id="__codelineno-10-2" name="__codelineno-10-2" href="#__codelineno-10-2"></a><span class="n">MinHeap</span><span class="w"> </span><span class="n">topKHeap</span><span class="p">(</span><span class="n">List</span><span class="o"><</span><span class="kt">int</span><span class="o">></span><span class="w"> </span><span class="n">nums</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">k</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-10-3" name="__codelineno-10-3" href="#__codelineno-10-3"></a><span class="w"> </span><span class="c1">// 将数组的前 k 个元素入堆</span>
|
||||
<a id="__codelineno-10-4" name="__codelineno-10-4" href="#__codelineno-10-4"></a><span class="w"> </span><span class="n">MinHeap</span><span class="w"> </span><span class="n">heap</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MinHeap</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">sublist</span><span class="p">(</span><span class="m">0</span><span class="p">,</span><span class="w"> </span><span class="n">k</span><span class="p">));</span>
|
||||
<a id="__codelineno-10-5" name="__codelineno-10-5" href="#__codelineno-10-5"></a><span class="w"> </span><span class="c1">// 从第 k+1 个元素开始,保持堆的长度为 k</span>
|
||||
<a id="__codelineno-10-6" name="__codelineno-10-6" href="#__codelineno-10-6"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">k</span><span class="p">;</span><span class="w"> </span><span class="n">i</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">length</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-10-7" name="__codelineno-10-7" href="#__codelineno-10-7"></a><span class="w"> </span><span class="c1">// 若当前元素大于堆顶元素,则将堆顶元素出堆、当前元素入堆</span>
|
||||
<a id="__codelineno-10-8" name="__codelineno-10-8" href="#__codelineno-10-8"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="n">heap</span><span class="p">.</span><span class="n">peek</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-10-9" name="__codelineno-10-9" href="#__codelineno-10-9"></a><span class="w"> </span><span class="n">heap</span><span class="p">.</span><span class="n">pop</span><span class="p">();</span>
|
||||
<a id="__codelineno-10-10" name="__codelineno-10-10" href="#__codelineno-10-10"></a><span class="w"> </span><span class="n">heap</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
|
||||
<a id="__codelineno-10-11" name="__codelineno-10-11" href="#__codelineno-10-11"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-10-12" name="__codelineno-10-12" href="#__codelineno-10-12"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-10-13" name="__codelineno-10-13" href="#__codelineno-10-13"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">heap</span><span class="p">;</span>
|
||||
<a id="__codelineno-10-14" name="__codelineno-10-14" href="#__codelineno-10-14"></a><span class="p">}</span>
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
|
||||
Reference in New Issue
Block a user