mirror of
https://github.com/krahets/hello-algo.git
synced 2026-07-09 22:16:06 +00:00
deploy
This commit is contained in:
@@ -3671,14 +3671,14 @@
|
||||
</ol>
|
||||
<p>也就是说,在能够解决问题的前提下,算法效率已成为衡量算法优劣的主要评价指标,它包括以下两个维度。</p>
|
||||
<ul>
|
||||
<li><strong>时间效率</strong>:算法运行速度的快慢。</li>
|
||||
<li><strong>时间效率</strong>:算法运行时间的长短。</li>
|
||||
<li><strong>空间效率</strong>:算法占用内存空间的大小。</li>
|
||||
</ul>
|
||||
<p>简而言之,<strong>我们的目标是设计“既快又省”的数据结构与算法</strong>。而有效地评估算法效率至关重要,因为只有这样,我们才能将各种算法进行对比,进而指导算法设计与优化过程。</p>
|
||||
<p>效率评估方法主要分为两种:实际测试、理论估算。</p>
|
||||
<h2 id="211">2.1.1 实际测试<a class="headerlink" href="#211" title="Permanent link">¶</a></h2>
|
||||
<p>假设我们现在有算法 <code>A</code> 和算法 <code>B</code> ,它们都能解决同一问题,现在需要对比这两个算法的效率。最直接的方法是找一台计算机,运行这两个算法,并监控记录它们的运行时间和内存占用情况。这种评估方式能够反映真实情况,但也存在较大的局限性。</p>
|
||||
<p>一方面,<strong>难以排除测试环境的干扰因素</strong>。硬件配置会影响算法的性能。比如在某台计算机中,算法 <code>A</code> 的运行时间比算法 <code>B</code> 短;但在另一台配置不同的计算机中,可能得到相反的测试结果。这意味着我们需要在各种机器上进行测试,统计平均效率,而这是不现实的。</p>
|
||||
<p>一方面,<strong>难以排除测试环境的干扰因素</strong>。硬件配置会影响算法的性能表现。比如一个算法的并行度较高,那么它就更适合在多核 CPU 上运行,一个算法的内存操作密集,那么它在高性能内存上的表现就会更好。也就是说,算法在不同的机器上的测试结果可能是不一致的。这意味着我们需要在各种机器上进行测试,统计平均效率,而这是不现实的。</p>
|
||||
<p>另一方面,<strong>展开完整测试非常耗费资源</strong>。随着输入数据量的变化,算法会表现出不同的效率。例如,在输入数据量较小时,算法 <code>A</code> 的运行时间比算法 <code>B</code> 短;而在输入数据量较大时,测试结果可能恰恰相反。因此,为了得到有说服力的结论,我们需要测试各种规模的输入数据,而这需要耗费大量的计算资源。</p>
|
||||
<h2 id="212">2.1.2 理论估算<a class="headerlink" href="#212" title="Permanent link">¶</a></h2>
|
||||
<p>由于实际测试具有较大的局限性,因此我们可以考虑仅通过一些计算来评估算法的效率。这种估算方法被称为<u>渐近复杂度分析(asymptotic complexity analysis)</u>,简称<u>复杂度分析</u>。</p>
|
||||
@@ -3688,8 +3688,9 @@
|
||||
<li>“随着输入数据大小的增加”意味着复杂度反映了算法运行效率与输入数据体量之间的关系。</li>
|
||||
<li>“时间和空间的增长趋势”表示复杂度分析关注的不是运行时间或占用空间的具体值,而是时间或空间增长的“快慢”。</li>
|
||||
</ul>
|
||||
<p><strong>复杂度分析克服了实际测试方法的弊端</strong>,体现在以下两个方面。</p>
|
||||
<p><strong>复杂度分析克服了实际测试方法的弊端</strong>,体现在以下几个方面。</p>
|
||||
<ul>
|
||||
<li>它无需实际运行代码,更加绿色节能。</li>
|
||||
<li>它独立于测试环境,分析结果适用于所有运行平台。</li>
|
||||
<li>它可以体现不同数据量下的算法效率,尤其是在大数据量下的算法性能。</li>
|
||||
</ul>
|
||||
|
||||
@@ -4383,7 +4383,7 @@
|
||||
<ul>
|
||||
<li><strong>时间复杂度能够有效评估算法效率</strong>。例如,算法 <code>B</code> 的运行时间呈线性增长,在 <span class="arithmatex">\(n > 1\)</span> 时比算法 <code>A</code> 更慢,在 <span class="arithmatex">\(n > 1000000\)</span> 时比算法 <code>C</code> 更慢。事实上,只要输入数据大小 <span class="arithmatex">\(n\)</span> 足够大,复杂度为“常数阶”的算法一定优于“线性阶”的算法,这正是时间增长趋势的含义。</li>
|
||||
<li><strong>时间复杂度的推算方法更简便</strong>。显然,运行平台和计算操作类型都与算法运行时间的增长趋势无关。因此在时间复杂度分析中,我们可以简单地将所有计算操作的执行时间视为相同的“单位时间”,从而将“计算操作运行时间统计”简化为“计算操作数量统计”,这样一来估算难度就大大降低了。</li>
|
||||
<li><strong>时间复杂度也存在一定的局限性</strong>。例如,尽管算法 <code>A</code> 和 <code>C</code> 的时间复杂度相同,但实际运行时间差别很大。同样,尽管算法 <code>B</code> 的时间复杂度比 <code>C</code> 高,但在输入数据大小 <span class="arithmatex">\(n\)</span> 较小时,算法 <code>B</code> 明显优于算法 <code>C</code> 。在这些情况下,我们很难仅凭时间复杂度判断算法效率的高低。当然,尽管存在上述问题,复杂度分析仍然是评判算法效率最有效且常用的方法。</li>
|
||||
<li><strong>时间复杂度也存在一定的局限性</strong>。例如,尽管算法 <code>A</code> 和 <code>C</code> 的时间复杂度相同,但实际运行时间差别很大。同样,尽管算法 <code>B</code> 的时间复杂度比 <code>C</code> 高,但在输入数据大小 <span class="arithmatex">\(n\)</span> 较小时,算法 <code>B</code> 明显优于算法 <code>C</code> 。对于此类情况,我们时常难以仅凭时间复杂度判断算法效率的高低。当然,尽管存在上述问题,复杂度分析仍然是评判算法效率最有效且常用的方法。</li>
|
||||
</ul>
|
||||
<h2 id="232">2.3.2 函数渐近上界<a class="headerlink" href="#232" title="Permanent link">¶</a></h2>
|
||||
<p>给定一个输入大小为 <span class="arithmatex">\(n\)</span> 的函数:</p>
|
||||
@@ -6617,10 +6617,12 @@ O(\log_m n) = O(\log_k n / \log_k m) = O(\log_k n)
|
||||
<a id="__codelineno-182-2" name="__codelineno-182-2" href="#__codelineno-182-2"></a><span class="w"> </span><span class="sd">"""线性对数阶"""</span>
|
||||
<a id="__codelineno-182-3" name="__codelineno-182-3" href="#__codelineno-182-3"></a> <span class="k">if</span> <span class="n">n</span> <span class="o"><=</span> <span class="mi">1</span><span class="p">:</span>
|
||||
<a id="__codelineno-182-4" name="__codelineno-182-4" href="#__codelineno-182-4"></a> <span class="k">return</span> <span class="mi">1</span>
|
||||
<a id="__codelineno-182-5" name="__codelineno-182-5" href="#__codelineno-182-5"></a> <span class="n">count</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="n">linear_log_recur</span><span class="p">(</span><span class="n">n</span> <span class="o">//</span> <span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="n">linear_log_recur</span><span class="p">(</span><span class="n">n</span> <span class="o">//</span> <span class="mi">2</span><span class="p">)</span>
|
||||
<a id="__codelineno-182-6" name="__codelineno-182-6" href="#__codelineno-182-6"></a> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
|
||||
<a id="__codelineno-182-7" name="__codelineno-182-7" href="#__codelineno-182-7"></a> <span class="n">count</span> <span class="o">+=</span> <span class="mi">1</span>
|
||||
<a id="__codelineno-182-8" name="__codelineno-182-8" href="#__codelineno-182-8"></a> <span class="k">return</span> <span class="n">count</span>
|
||||
<a id="__codelineno-182-5" name="__codelineno-182-5" href="#__codelineno-182-5"></a> <span class="c1"># 一分为二,子问题的规模减小一半</span>
|
||||
<a id="__codelineno-182-6" name="__codelineno-182-6" href="#__codelineno-182-6"></a> <span class="n">count</span> <span class="o">=</span> <span class="n">linear_log_recur</span><span class="p">(</span><span class="n">n</span> <span class="o">//</span> <span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="n">linear_log_recur</span><span class="p">(</span><span class="n">n</span> <span class="o">//</span> <span class="mi">2</span><span class="p">)</span>
|
||||
<a id="__codelineno-182-7" name="__codelineno-182-7" href="#__codelineno-182-7"></a> <span class="c1"># 当前子问题包含 n 个操作</span>
|
||||
<a id="__codelineno-182-8" name="__codelineno-182-8" href="#__codelineno-182-8"></a> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
|
||||
<a id="__codelineno-182-9" name="__codelineno-182-9" href="#__codelineno-182-9"></a> <span class="n">count</span> <span class="o">+=</span> <span class="mi">1</span>
|
||||
<a id="__codelineno-182-10" name="__codelineno-182-10" href="#__codelineno-182-10"></a> <span class="k">return</span> <span class="n">count</span>
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
|
||||
Reference in New Issue
Block a user