mirror of
https://github.com/krahets/hello-algo.git
synced 2024-12-25 02:06:28 +08:00
deploy
This commit is contained in:
parent
421bd4ef2c
commit
e5eb0ab492
19 changed files with 734 additions and 744 deletions
|
@ -3841,27 +3841,23 @@
|
|||
</div>
|
||||
<div class="tabbed-block">
|
||||
<div class="highlight"><span class="filename">binary_search_tree.rs</span><pre><span></span><code><a id="__codelineno-9-1" name="__codelineno-9-1" href="#__codelineno-9-1"></a><span class="cm">/* 查找节点 */</span>
|
||||
<a id="__codelineno-9-2" name="__codelineno-9-2" href="#__codelineno-9-2"></a><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">search</span><span class="p">(</span><span class="o">&</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">num</span>: <span class="kt">i32</span><span class="p">)</span><span class="w"> </span>-> <span class="nb">Option</span><span class="o"><</span><span class="n">TreeNodeRc</span><span class="o">></span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-9-2" name="__codelineno-9-2" href="#__codelineno-9-2"></a><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">search</span><span class="p">(</span><span class="o">&</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">num</span>: <span class="kt">i32</span><span class="p">)</span><span class="w"> </span>-> <span class="nc">OptionTreeNodeRc</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-9-3" name="__codelineno-9-3" href="#__codelineno-9-3"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">root</span><span class="p">.</span><span class="n">clone</span><span class="p">();</span>
|
||||
<a id="__codelineno-9-4" name="__codelineno-9-4" href="#__codelineno-9-4"></a>
|
||||
<a id="__codelineno-9-5" name="__codelineno-9-5" href="#__codelineno-9-5"></a><span class="w"> </span><span class="c1">// 循环查找,越过叶节点后跳出</span>
|
||||
<a id="__codelineno-9-6" name="__codelineno-9-6" href="#__codelineno-9-6"></a><span class="w"> </span><span class="k">while</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">node</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="n">clone</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-9-7" name="__codelineno-9-7" href="#__codelineno-9-7"></a><span class="w"> </span><span class="c1">// 目标节点在 cur 的右子树中</span>
|
||||
<a id="__codelineno-9-8" name="__codelineno-9-8" href="#__codelineno-9-8"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">val</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">num</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-9-9" name="__codelineno-9-9" href="#__codelineno-9-9"></a><span class="w"> </span><span class="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">right</span><span class="p">.</span><span class="n">clone</span><span class="p">();</span>
|
||||
<a id="__codelineno-9-10" name="__codelineno-9-10" href="#__codelineno-9-10"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-9-11" name="__codelineno-9-11" href="#__codelineno-9-11"></a><span class="w"> </span><span class="c1">// 目标节点在 cur 的左子树中</span>
|
||||
<a id="__codelineno-9-12" name="__codelineno-9-12" href="#__codelineno-9-12"></a><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">val</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="n">num</span><span class="w"> </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="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">left</span><span class="p">.</span><span class="n">clone</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="p">}</span>
|
||||
<a id="__codelineno-9-15" name="__codelineno-9-15" href="#__codelineno-9-15"></a><span class="w"> </span><span class="c1">// 找到目标节点,跳出循环</span>
|
||||
<a id="__codelineno-9-16" name="__codelineno-9-16" href="#__codelineno-9-16"></a><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-9-17" name="__codelineno-9-17" href="#__codelineno-9-17"></a><span class="w"> </span><span class="k">break</span><span class="p">;</span>
|
||||
<a id="__codelineno-9-18" name="__codelineno-9-18" href="#__codelineno-9-18"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-9-19" name="__codelineno-9-19" href="#__codelineno-9-19"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-9-20" name="__codelineno-9-20" href="#__codelineno-9-20"></a><span class="w"> </span><span class="c1">// 返回目标节点</span>
|
||||
<a id="__codelineno-9-21" name="__codelineno-9-21" href="#__codelineno-9-21"></a><span class="w"> </span><span class="n">cur</span>
|
||||
<a id="__codelineno-9-22" name="__codelineno-9-22" href="#__codelineno-9-22"></a><span class="p">}</span>
|
||||
<a id="__codelineno-9-4" name="__codelineno-9-4" href="#__codelineno-9-4"></a><span class="w"> </span><span class="c1">// 循环查找,越过叶节点后跳出</span>
|
||||
<a id="__codelineno-9-5" name="__codelineno-9-5" href="#__codelineno-9-5"></a><span class="w"> </span><span class="k">while</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">node</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="n">clone</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-9-6" name="__codelineno-9-6" href="#__codelineno-9-6"></a><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">num</span><span class="p">.</span><span class="n">cmp</span><span class="p">(</span><span class="o">&</span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">val</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-9-7" name="__codelineno-9-7" href="#__codelineno-9-7"></a><span class="w"> </span><span class="c1">// 目标节点在 cur 的右子树中</span>
|
||||
<a id="__codelineno-9-8" name="__codelineno-9-8" href="#__codelineno-9-8"></a><span class="w"> </span><span class="n">Ordering</span>::<span class="n">Greater</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">right</span><span class="p">.</span><span class="n">clone</span><span class="p">(),</span>
|
||||
<a id="__codelineno-9-9" name="__codelineno-9-9" href="#__codelineno-9-9"></a><span class="w"> </span><span class="c1">// 目标节点在 cur 的左子树中</span>
|
||||
<a id="__codelineno-9-10" name="__codelineno-9-10" href="#__codelineno-9-10"></a><span class="w"> </span><span class="n">Ordering</span>::<span class="n">Less</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">left</span><span class="p">.</span><span class="n">clone</span><span class="p">(),</span>
|
||||
<a id="__codelineno-9-11" name="__codelineno-9-11" href="#__codelineno-9-11"></a><span class="w"> </span><span class="c1">// 找到目标节点,跳出循环</span>
|
||||
<a id="__codelineno-9-12" name="__codelineno-9-12" href="#__codelineno-9-12"></a><span class="w"> </span><span class="n">Ordering</span>::<span class="n">Equal</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="k">break</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="p">}</span>
|
||||
<a id="__codelineno-9-14" name="__codelineno-9-14" href="#__codelineno-9-14"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-9-15" name="__codelineno-9-15" href="#__codelineno-9-15"></a>
|
||||
<a id="__codelineno-9-16" name="__codelineno-9-16" href="#__codelineno-9-16"></a><span class="w"> </span><span class="c1">// 返回目标节点</span>
|
||||
<a id="__codelineno-9-17" name="__codelineno-9-17" href="#__codelineno-9-17"></a><span class="w"> </span><span class="n">cur</span>
|
||||
<a id="__codelineno-9-18" name="__codelineno-9-18" href="#__codelineno-9-18"></a><span class="p">}</span>
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
|
@ -4216,29 +4212,30 @@
|
|||
<a id="__codelineno-21-9" name="__codelineno-21-9" href="#__codelineno-21-9"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">pre</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">None</span><span class="p">;</span>
|
||||
<a id="__codelineno-21-10" name="__codelineno-21-10" href="#__codelineno-21-10"></a><span class="w"> </span><span class="c1">// 循环查找,越过叶节点后跳出</span>
|
||||
<a id="__codelineno-21-11" name="__codelineno-21-11" href="#__codelineno-21-11"></a><span class="w"> </span><span class="k">while</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">node</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="n">clone</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-21-12" name="__codelineno-21-12" href="#__codelineno-21-12"></a><span class="w"> </span><span class="c1">// 找到重复节点,直接返回</span>
|
||||
<a id="__codelineno-21-13" name="__codelineno-21-13" href="#__codelineno-21-13"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">val</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">num</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-21-14" name="__codelineno-21-14" href="#__codelineno-21-14"></a><span class="w"> </span><span class="k">return</span><span class="p">;</span>
|
||||
<a id="__codelineno-21-15" name="__codelineno-21-15" href="#__codelineno-21-15"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-21-16" name="__codelineno-21-16" href="#__codelineno-21-16"></a><span class="w"> </span><span class="c1">// 插入位置在 cur 的右子树中</span>
|
||||
<a id="__codelineno-21-17" name="__codelineno-21-17" href="#__codelineno-21-17"></a><span class="w"> </span><span class="n">pre</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="n">clone</span><span class="p">();</span>
|
||||
<a id="__codelineno-21-18" name="__codelineno-21-18" href="#__codelineno-21-18"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">val</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">num</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-21-19" name="__codelineno-21-19" href="#__codelineno-21-19"></a><span class="w"> </span><span class="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">right</span><span class="p">.</span><span class="n">clone</span><span class="p">();</span>
|
||||
<a id="__codelineno-21-20" name="__codelineno-21-20" href="#__codelineno-21-20"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-21-21" name="__codelineno-21-21" href="#__codelineno-21-21"></a><span class="w"> </span><span class="c1">// 插入位置在 cur 的左子树中</span>
|
||||
<a id="__codelineno-21-22" name="__codelineno-21-22" href="#__codelineno-21-22"></a><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-21-23" name="__codelineno-21-23" href="#__codelineno-21-23"></a><span class="w"> </span><span class="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">left</span><span class="p">.</span><span class="n">clone</span><span class="p">();</span>
|
||||
<a id="__codelineno-21-24" name="__codelineno-21-24" href="#__codelineno-21-24"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-21-25" name="__codelineno-21-25" href="#__codelineno-21-25"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-21-26" name="__codelineno-21-26" href="#__codelineno-21-26"></a><span class="w"> </span><span class="c1">// 插入节点</span>
|
||||
<a id="__codelineno-21-27" name="__codelineno-21-27" href="#__codelineno-21-27"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">node</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">TreeNode</span>::<span class="n">new</span><span class="p">(</span><span class="n">num</span><span class="p">);</span>
|
||||
<a id="__codelineno-21-12" name="__codelineno-21-12" href="#__codelineno-21-12"></a><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">num</span><span class="p">.</span><span class="n">cmp</span><span class="p">(</span><span class="o">&</span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">val</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-21-13" name="__codelineno-21-13" href="#__codelineno-21-13"></a><span class="w"> </span><span class="c1">// 找到重复节点,直接返回</span>
|
||||
<a id="__codelineno-21-14" name="__codelineno-21-14" href="#__codelineno-21-14"></a><span class="w"> </span><span class="n">Ordering</span>::<span class="n">Equal</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="k">return</span><span class="p">,</span>
|
||||
<a id="__codelineno-21-15" name="__codelineno-21-15" href="#__codelineno-21-15"></a><span class="w"> </span><span class="c1">// 插入位置在 cur 的右子树中</span>
|
||||
<a id="__codelineno-21-16" name="__codelineno-21-16" href="#__codelineno-21-16"></a><span class="w"> </span><span class="n">Ordering</span>::<span class="n">Greater</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-21-17" name="__codelineno-21-17" href="#__codelineno-21-17"></a><span class="w"> </span><span class="n">pre</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="n">clone</span><span class="p">();</span>
|
||||
<a id="__codelineno-21-18" name="__codelineno-21-18" href="#__codelineno-21-18"></a><span class="w"> </span><span class="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">right</span><span class="p">.</span><span class="n">clone</span><span class="p">();</span>
|
||||
<a id="__codelineno-21-19" name="__codelineno-21-19" href="#__codelineno-21-19"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-21-20" name="__codelineno-21-20" href="#__codelineno-21-20"></a><span class="w"> </span><span class="c1">// 插入位置在 cur 的左子树中</span>
|
||||
<a id="__codelineno-21-21" name="__codelineno-21-21" href="#__codelineno-21-21"></a><span class="w"> </span><span class="n">Ordering</span>::<span class="n">Less</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-21-22" name="__codelineno-21-22" href="#__codelineno-21-22"></a><span class="w"> </span><span class="n">pre</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="n">clone</span><span class="p">();</span>
|
||||
<a id="__codelineno-21-23" name="__codelineno-21-23" href="#__codelineno-21-23"></a><span class="w"> </span><span class="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">left</span><span class="p">.</span><span class="n">clone</span><span class="p">();</span>
|
||||
<a id="__codelineno-21-24" name="__codelineno-21-24" href="#__codelineno-21-24"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-21-25" name="__codelineno-21-25" href="#__codelineno-21-25"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-21-26" name="__codelineno-21-26" href="#__codelineno-21-26"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-21-27" name="__codelineno-21-27" href="#__codelineno-21-27"></a><span class="w"> </span><span class="c1">// 插入节点</span>
|
||||
<a id="__codelineno-21-28" name="__codelineno-21-28" href="#__codelineno-21-28"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">pre</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">pre</span><span class="p">.</span><span class="n">unwrap</span><span class="p">();</span>
|
||||
<a id="__codelineno-21-29" name="__codelineno-21-29" href="#__codelineno-21-29"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">pre</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">val</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">num</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-21-30" name="__codelineno-21-30" href="#__codelineno-21-30"></a><span class="w"> </span><span class="n">pre</span><span class="p">.</span><span class="n">borrow_mut</span><span class="p">().</span><span class="n">right</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">Rc</span>::<span class="n">clone</span><span class="p">(</span><span class="o">&</span><span class="n">node</span><span class="p">));</span>
|
||||
<a id="__codelineno-21-31" name="__codelineno-21-31" href="#__codelineno-21-31"></a><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-21-32" name="__codelineno-21-32" href="#__codelineno-21-32"></a><span class="w"> </span><span class="n">pre</span><span class="p">.</span><span class="n">borrow_mut</span><span class="p">().</span><span class="n">left</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">Rc</span>::<span class="n">clone</span><span class="p">(</span><span class="o">&</span><span class="n">node</span><span class="p">));</span>
|
||||
<a id="__codelineno-21-33" name="__codelineno-21-33" href="#__codelineno-21-33"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-21-34" name="__codelineno-21-34" href="#__codelineno-21-34"></a><span class="p">}</span>
|
||||
<a id="__codelineno-21-29" name="__codelineno-21-29" href="#__codelineno-21-29"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">node</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">TreeNode</span>::<span class="n">new</span><span class="p">(</span><span class="n">num</span><span class="p">));</span>
|
||||
<a id="__codelineno-21-30" name="__codelineno-21-30" href="#__codelineno-21-30"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">num</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="n">pre</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">val</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-21-31" name="__codelineno-21-31" href="#__codelineno-21-31"></a><span class="w"> </span><span class="n">pre</span><span class="p">.</span><span class="n">borrow_mut</span><span class="p">().</span><span class="n">right</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">node</span><span class="p">;</span>
|
||||
<a id="__codelineno-21-32" name="__codelineno-21-32" href="#__codelineno-21-32"></a><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-21-33" name="__codelineno-21-33" href="#__codelineno-21-33"></a><span class="w"> </span><span class="n">pre</span><span class="p">.</span><span class="n">borrow_mut</span><span class="p">().</span><span class="n">left</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">node</span><span class="p">;</span>
|
||||
<a id="__codelineno-21-34" name="__codelineno-21-34" href="#__codelineno-21-34"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-21-35" name="__codelineno-21-35" href="#__codelineno-21-35"></a><span class="p">}</span>
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
|
@ -4840,61 +4837,65 @@
|
|||
<a id="__codelineno-33-8" name="__codelineno-33-8" href="#__codelineno-33-8"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">pre</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">None</span><span class="p">;</span>
|
||||
<a id="__codelineno-33-9" name="__codelineno-33-9" href="#__codelineno-33-9"></a><span class="w"> </span><span class="c1">// 循环查找,越过叶节点后跳出</span>
|
||||
<a id="__codelineno-33-10" name="__codelineno-33-10" href="#__codelineno-33-10"></a><span class="w"> </span><span class="k">while</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">node</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="n">clone</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-11" name="__codelineno-33-11" href="#__codelineno-33-11"></a><span class="w"> </span><span class="c1">// 找到待删除节点,跳出循环</span>
|
||||
<a id="__codelineno-33-12" name="__codelineno-33-12" href="#__codelineno-33-12"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">val</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">num</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-13" name="__codelineno-33-13" href="#__codelineno-33-13"></a><span class="w"> </span><span class="k">break</span><span class="p">;</span>
|
||||
<a id="__codelineno-33-14" name="__codelineno-33-14" href="#__codelineno-33-14"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-33-15" name="__codelineno-33-15" href="#__codelineno-33-15"></a><span class="w"> </span><span class="c1">// 待删除节点在 cur 的右子树中</span>
|
||||
<a id="__codelineno-33-16" name="__codelineno-33-16" href="#__codelineno-33-16"></a><span class="w"> </span><span class="n">pre</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="n">clone</span><span class="p">();</span>
|
||||
<a id="__codelineno-33-17" name="__codelineno-33-17" href="#__codelineno-33-17"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">val</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">num</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-18" name="__codelineno-33-18" href="#__codelineno-33-18"></a><span class="w"> </span><span class="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">right</span><span class="p">.</span><span class="n">clone</span><span class="p">();</span>
|
||||
<a id="__codelineno-33-19" name="__codelineno-33-19" href="#__codelineno-33-19"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-33-20" name="__codelineno-33-20" href="#__codelineno-33-20"></a><span class="w"> </span><span class="c1">// 待删除节点在 cur 的左子树中</span>
|
||||
<a id="__codelineno-33-21" name="__codelineno-33-21" href="#__codelineno-33-21"></a><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-22" name="__codelineno-33-22" href="#__codelineno-33-22"></a><span class="w"> </span><span class="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">left</span><span class="p">.</span><span class="n">clone</span><span class="p">();</span>
|
||||
<a id="__codelineno-33-23" name="__codelineno-33-23" href="#__codelineno-33-23"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-33-24" name="__codelineno-33-24" href="#__codelineno-33-24"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-33-25" name="__codelineno-33-25" href="#__codelineno-33-25"></a><span class="w"> </span><span class="c1">// 若无待删除节点,则直接返回</span>
|
||||
<a id="__codelineno-33-26" name="__codelineno-33-26" href="#__codelineno-33-26"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="n">is_none</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-27" name="__codelineno-33-27" href="#__codelineno-33-27"></a><span class="w"> </span><span class="k">return</span><span class="p">;</span>
|
||||
<a id="__codelineno-33-28" name="__codelineno-33-28" href="#__codelineno-33-28"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-33-29" name="__codelineno-33-29" href="#__codelineno-33-29"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="n">unwrap</span><span class="p">();</span>
|
||||
<a id="__codelineno-33-30" name="__codelineno-33-30" href="#__codelineno-33-30"></a><span class="w"> </span><span class="c1">// 子节点数量 = 0 or 1</span>
|
||||
<a id="__codelineno-33-31" name="__codelineno-33-31" href="#__codelineno-33-31"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">left</span><span class="p">.</span><span class="n">is_none</span><span class="p">()</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">right</span><span class="p">.</span><span class="n">is_none</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-32" name="__codelineno-33-32" href="#__codelineno-33-32"></a><span class="w"> </span><span class="c1">// 当子节点数量 = 0 / 1 时, child = nullptr / 该子节点</span>
|
||||
<a id="__codelineno-33-33" name="__codelineno-33-33" href="#__codelineno-33-33"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">child</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">left</span><span class="p">.</span><span class="n">clone</span><span class="p">().</span><span class="n">or_else</span><span class="p">(</span><span class="o">||</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">right</span><span class="p">.</span><span class="n">clone</span><span class="p">());</span>
|
||||
<a id="__codelineno-33-34" name="__codelineno-33-34" href="#__codelineno-33-34"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">pre</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">pre</span><span class="p">.</span><span class="n">unwrap</span><span class="p">();</span>
|
||||
<a id="__codelineno-33-35" name="__codelineno-33-35" href="#__codelineno-33-35"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">left</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">pre</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">left</span><span class="p">.</span><span class="n">clone</span><span class="p">().</span><span class="n">unwrap</span><span class="p">();</span>
|
||||
<a id="__codelineno-33-36" name="__codelineno-33-36" href="#__codelineno-33-36"></a><span class="w"> </span><span class="c1">// 删除节点 cur</span>
|
||||
<a id="__codelineno-33-37" name="__codelineno-33-37" href="#__codelineno-33-37"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="o">!</span><span class="n">Rc</span>::<span class="n">ptr_eq</span><span class="p">(</span><span class="o">&</span><span class="n">cur</span><span class="p">,</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">root</span><span class="p">.</span><span class="n">as_ref</span><span class="p">().</span><span class="n">unwrap</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-38" name="__codelineno-33-38" href="#__codelineno-33-38"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">Rc</span>::<span class="n">ptr_eq</span><span class="p">(</span><span class="o">&</span><span class="n">left</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">cur</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-39" name="__codelineno-33-39" href="#__codelineno-33-39"></a><span class="w"> </span><span class="n">pre</span><span class="p">.</span><span class="n">borrow_mut</span><span class="p">().</span><span class="n">left</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">child</span><span class="p">;</span>
|
||||
<a id="__codelineno-33-40" name="__codelineno-33-40" href="#__codelineno-33-40"></a><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-41" name="__codelineno-33-41" href="#__codelineno-33-41"></a><span class="w"> </span><span class="n">pre</span><span class="p">.</span><span class="n">borrow_mut</span><span class="p">().</span><span class="n">right</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">child</span><span class="p">;</span>
|
||||
<a id="__codelineno-33-42" name="__codelineno-33-42" href="#__codelineno-33-42"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-33-43" name="__codelineno-33-43" href="#__codelineno-33-43"></a><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-44" name="__codelineno-33-44" href="#__codelineno-33-44"></a><span class="w"> </span><span class="c1">// 若删除节点为根节点,则重新指定根节点</span>
|
||||
<a id="__codelineno-33-45" name="__codelineno-33-45" href="#__codelineno-33-45"></a><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">root</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">child</span><span class="p">;</span>
|
||||
<a id="__codelineno-33-46" name="__codelineno-33-46" href="#__codelineno-33-46"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-33-47" name="__codelineno-33-47" href="#__codelineno-33-47"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-33-48" name="__codelineno-33-48" href="#__codelineno-33-48"></a><span class="w"> </span><span class="c1">// 子节点数量 = 2</span>
|
||||
<a id="__codelineno-33-49" name="__codelineno-33-49" href="#__codelineno-33-49"></a><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-50" name="__codelineno-33-50" href="#__codelineno-33-50"></a><span class="w"> </span><span class="c1">// 获取中序遍历中 cur 的下一个节点</span>
|
||||
<a id="__codelineno-33-51" name="__codelineno-33-51" href="#__codelineno-33-51"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">tmp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">right</span><span class="p">.</span><span class="n">clone</span><span class="p">();</span>
|
||||
<a id="__codelineno-33-52" name="__codelineno-33-52" href="#__codelineno-33-52"></a><span class="w"> </span><span class="k">while</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">node</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tmp</span><span class="p">.</span><span class="n">clone</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-53" name="__codelineno-33-53" href="#__codelineno-33-53"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">left</span><span class="p">.</span><span class="n">is_some</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-54" name="__codelineno-33-54" href="#__codelineno-33-54"></a><span class="w"> </span><span class="n">tmp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">left</span><span class="p">.</span><span class="n">clone</span><span class="p">();</span>
|
||||
<a id="__codelineno-33-55" name="__codelineno-33-55" href="#__codelineno-33-55"></a><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-56" name="__codelineno-33-56" href="#__codelineno-33-56"></a><span class="w"> </span><span class="k">break</span><span class="p">;</span>
|
||||
<a id="__codelineno-33-57" name="__codelineno-33-57" href="#__codelineno-33-57"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-33-58" name="__codelineno-33-58" href="#__codelineno-33-58"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-33-59" name="__codelineno-33-59" href="#__codelineno-33-59"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">tmpval</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tmp</span><span class="p">.</span><span class="n">unwrap</span><span class="p">().</span><span class="n">borrow</span><span class="p">().</span><span class="n">val</span><span class="p">;</span>
|
||||
<a id="__codelineno-33-60" name="__codelineno-33-60" href="#__codelineno-33-60"></a><span class="w"> </span><span class="c1">// 递归删除节点 tmp</span>
|
||||
<a id="__codelineno-33-61" name="__codelineno-33-61" href="#__codelineno-33-61"></a><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">remove</span><span class="p">(</span><span class="n">tmpval</span><span class="p">);</span>
|
||||
<a id="__codelineno-33-62" name="__codelineno-33-62" href="#__codelineno-33-62"></a><span class="w"> </span><span class="c1">// 用 tmp 覆盖 cur</span>
|
||||
<a id="__codelineno-33-63" name="__codelineno-33-63" href="#__codelineno-33-63"></a><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="n">borrow_mut</span><span class="p">().</span><span class="n">val</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tmpval</span><span class="p">;</span>
|
||||
<a id="__codelineno-33-64" name="__codelineno-33-64" href="#__codelineno-33-64"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-33-65" name="__codelineno-33-65" href="#__codelineno-33-65"></a><span class="p">}</span>
|
||||
<a id="__codelineno-33-11" name="__codelineno-33-11" href="#__codelineno-33-11"></a><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">num</span><span class="p">.</span><span class="n">cmp</span><span class="p">(</span><span class="o">&</span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">val</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-12" name="__codelineno-33-12" href="#__codelineno-33-12"></a><span class="w"> </span><span class="c1">// 找到待删除节点,跳出循环</span>
|
||||
<a id="__codelineno-33-13" name="__codelineno-33-13" href="#__codelineno-33-13"></a><span class="w"> </span><span class="n">Ordering</span>::<span class="n">Equal</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="k">break</span><span class="p">,</span>
|
||||
<a id="__codelineno-33-14" name="__codelineno-33-14" href="#__codelineno-33-14"></a><span class="w"> </span><span class="c1">// 待删除节点在 cur 的右子树中</span>
|
||||
<a id="__codelineno-33-15" name="__codelineno-33-15" href="#__codelineno-33-15"></a><span class="w"> </span><span class="n">Ordering</span>::<span class="n">Greater</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-16" name="__codelineno-33-16" href="#__codelineno-33-16"></a><span class="w"> </span><span class="n">pre</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="n">clone</span><span class="p">();</span>
|
||||
<a id="__codelineno-33-17" name="__codelineno-33-17" href="#__codelineno-33-17"></a><span class="w"> </span><span class="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">right</span><span class="p">.</span><span class="n">clone</span><span class="p">();</span>
|
||||
<a id="__codelineno-33-18" name="__codelineno-33-18" href="#__codelineno-33-18"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-33-19" name="__codelineno-33-19" href="#__codelineno-33-19"></a><span class="w"> </span><span class="c1">// 待删除节点在 cur 的左子树中</span>
|
||||
<a id="__codelineno-33-20" name="__codelineno-33-20" href="#__codelineno-33-20"></a><span class="w"> </span><span class="n">Ordering</span>::<span class="n">Less</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-21" name="__codelineno-33-21" href="#__codelineno-33-21"></a><span class="w"> </span><span class="n">pre</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="n">clone</span><span class="p">();</span>
|
||||
<a id="__codelineno-33-22" name="__codelineno-33-22" href="#__codelineno-33-22"></a><span class="w"> </span><span class="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">left</span><span class="p">.</span><span class="n">clone</span><span class="p">();</span>
|
||||
<a id="__codelineno-33-23" name="__codelineno-33-23" href="#__codelineno-33-23"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-33-24" name="__codelineno-33-24" href="#__codelineno-33-24"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-33-25" name="__codelineno-33-25" href="#__codelineno-33-25"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-33-26" name="__codelineno-33-26" href="#__codelineno-33-26"></a><span class="w"> </span><span class="c1">// 若无待删除节点,则直接返回</span>
|
||||
<a id="__codelineno-33-27" name="__codelineno-33-27" href="#__codelineno-33-27"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="n">is_none</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-28" name="__codelineno-33-28" href="#__codelineno-33-28"></a><span class="w"> </span><span class="k">return</span><span class="p">;</span>
|
||||
<a id="__codelineno-33-29" name="__codelineno-33-29" href="#__codelineno-33-29"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-33-30" name="__codelineno-33-30" href="#__codelineno-33-30"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">cur</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="n">unwrap</span><span class="p">();</span>
|
||||
<a id="__codelineno-33-31" name="__codelineno-33-31" href="#__codelineno-33-31"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="p">(</span><span class="n">left_child</span><span class="p">,</span><span class="w"> </span><span class="n">right_child</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">cur</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">left</span><span class="p">.</span><span class="n">clone</span><span class="p">(),</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">right</span><span class="p">.</span><span class="n">clone</span><span class="p">());</span>
|
||||
<a id="__codelineno-33-32" name="__codelineno-33-32" href="#__codelineno-33-32"></a><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="p">(</span><span class="n">left_child</span><span class="p">.</span><span class="n">clone</span><span class="p">(),</span><span class="w"> </span><span class="n">right_child</span><span class="p">.</span><span class="n">clone</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-33" name="__codelineno-33-33" href="#__codelineno-33-33"></a><span class="w"> </span><span class="c1">// 子节点数量 = 0 or 1</span>
|
||||
<a id="__codelineno-33-34" name="__codelineno-33-34" href="#__codelineno-33-34"></a><span class="w"> </span><span class="p">(</span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">)</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="p">(</span><span class="nb">Some</span><span class="p">(</span><span class="n">_</span><span class="p">),</span><span class="w"> </span><span class="nb">None</span><span class="p">)</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="p">(</span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">_</span><span class="p">))</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-35" name="__codelineno-33-35" href="#__codelineno-33-35"></a><span class="w"> </span><span class="c1">// 当子节点数量 = 0 / 1 时, child = nullptr / 该子节点</span>
|
||||
<a id="__codelineno-33-36" name="__codelineno-33-36" href="#__codelineno-33-36"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">child</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">left_child</span><span class="p">.</span><span class="n">or</span><span class="p">(</span><span class="n">right_child</span><span class="p">);</span>
|
||||
<a id="__codelineno-33-37" name="__codelineno-33-37" href="#__codelineno-33-37"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">pre</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">pre</span><span class="p">.</span><span class="n">unwrap</span><span class="p">();</span>
|
||||
<a id="__codelineno-33-38" name="__codelineno-33-38" href="#__codelineno-33-38"></a><span class="w"> </span><span class="c1">// 删除节点 cur</span>
|
||||
<a id="__codelineno-33-39" name="__codelineno-33-39" href="#__codelineno-33-39"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="o">!</span><span class="n">Rc</span>::<span class="n">ptr_eq</span><span class="p">(</span><span class="o">&</span><span class="n">cur</span><span class="p">,</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">root</span><span class="p">.</span><span class="n">as_ref</span><span class="p">().</span><span class="n">unwrap</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-40" name="__codelineno-33-40" href="#__codelineno-33-40"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">left</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">pre</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">left</span><span class="p">.</span><span class="n">clone</span><span class="p">();</span>
|
||||
<a id="__codelineno-33-41" name="__codelineno-33-41" href="#__codelineno-33-41"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">left</span><span class="p">.</span><span class="n">is_some</span><span class="p">()</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">Rc</span>::<span class="n">ptr_eq</span><span class="p">(</span><span class="o">&</span><span class="n">left</span><span class="p">.</span><span class="n">as_ref</span><span class="p">().</span><span class="n">unwrap</span><span class="p">(),</span><span class="w"> </span><span class="o">&</span><span class="n">cur</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-42" name="__codelineno-33-42" href="#__codelineno-33-42"></a><span class="w"> </span><span class="n">pre</span><span class="p">.</span><span class="n">borrow_mut</span><span class="p">().</span><span class="n">left</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">child</span><span class="p">;</span>
|
||||
<a id="__codelineno-33-43" name="__codelineno-33-43" href="#__codelineno-33-43"></a><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-44" name="__codelineno-33-44" href="#__codelineno-33-44"></a><span class="w"> </span><span class="n">pre</span><span class="p">.</span><span class="n">borrow_mut</span><span class="p">().</span><span class="n">right</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">child</span><span class="p">;</span>
|
||||
<a id="__codelineno-33-45" name="__codelineno-33-45" href="#__codelineno-33-45"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-33-46" name="__codelineno-33-46" href="#__codelineno-33-46"></a><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-47" name="__codelineno-33-47" href="#__codelineno-33-47"></a><span class="w"> </span><span class="c1">// 若删除节点为根节点,则重新指定根节点</span>
|
||||
<a id="__codelineno-33-48" name="__codelineno-33-48" href="#__codelineno-33-48"></a><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">root</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">child</span><span class="p">;</span>
|
||||
<a id="__codelineno-33-49" name="__codelineno-33-49" href="#__codelineno-33-49"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-33-50" name="__codelineno-33-50" href="#__codelineno-33-50"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-33-51" name="__codelineno-33-51" href="#__codelineno-33-51"></a><span class="w"> </span><span class="c1">// 子节点数量 = 2</span>
|
||||
<a id="__codelineno-33-52" name="__codelineno-33-52" href="#__codelineno-33-52"></a><span class="w"> </span><span class="p">(</span><span class="nb">Some</span><span class="p">(</span><span class="n">_</span><span class="p">),</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">_</span><span class="p">))</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-53" name="__codelineno-33-53" href="#__codelineno-33-53"></a><span class="w"> </span><span class="c1">// 获取中序遍历中 cur 的下一个节点</span>
|
||||
<a id="__codelineno-33-54" name="__codelineno-33-54" href="#__codelineno-33-54"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">tmp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">right</span><span class="p">.</span><span class="n">clone</span><span class="p">();</span>
|
||||
<a id="__codelineno-33-55" name="__codelineno-33-55" href="#__codelineno-33-55"></a><span class="w"> </span><span class="k">while</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">node</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tmp</span><span class="p">.</span><span class="n">clone</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-56" name="__codelineno-33-56" href="#__codelineno-33-56"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">left</span><span class="p">.</span><span class="n">is_some</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-57" name="__codelineno-33-57" href="#__codelineno-33-57"></a><span class="w"> </span><span class="n">tmp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">node</span><span class="p">.</span><span class="n">borrow</span><span class="p">().</span><span class="n">left</span><span class="p">.</span><span class="n">clone</span><span class="p">();</span>
|
||||
<a id="__codelineno-33-58" name="__codelineno-33-58" href="#__codelineno-33-58"></a><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-33-59" name="__codelineno-33-59" href="#__codelineno-33-59"></a><span class="w"> </span><span class="k">break</span><span class="p">;</span>
|
||||
<a id="__codelineno-33-60" name="__codelineno-33-60" href="#__codelineno-33-60"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-33-61" name="__codelineno-33-61" href="#__codelineno-33-61"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-33-62" name="__codelineno-33-62" href="#__codelineno-33-62"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">tmpval</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tmp</span><span class="p">.</span><span class="n">unwrap</span><span class="p">().</span><span class="n">borrow</span><span class="p">().</span><span class="n">val</span><span class="p">;</span>
|
||||
<a id="__codelineno-33-63" name="__codelineno-33-63" href="#__codelineno-33-63"></a><span class="w"> </span><span class="c1">// 递归删除节点 tmp</span>
|
||||
<a id="__codelineno-33-64" name="__codelineno-33-64" href="#__codelineno-33-64"></a><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">remove</span><span class="p">(</span><span class="n">tmpval</span><span class="p">);</span>
|
||||
<a id="__codelineno-33-65" name="__codelineno-33-65" href="#__codelineno-33-65"></a><span class="w"> </span><span class="c1">// 用 tmp 覆盖 cur</span>
|
||||
<a id="__codelineno-33-66" name="__codelineno-33-66" href="#__codelineno-33-66"></a><span class="w"> </span><span class="n">cur</span><span class="p">.</span><span class="n">borrow_mut</span><span class="p">().</span><span class="n">val</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tmpval</span><span class="p">;</span>
|
||||
<a id="__codelineno-33-67" name="__codelineno-33-67" href="#__codelineno-33-67"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-33-68" name="__codelineno-33-68" href="#__codelineno-33-68"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-33-69" name="__codelineno-33-69" href="#__codelineno-33-69"></a><span class="p">}</span>
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
|
|
|
@ -812,8 +812,8 @@
|
|||
</div>
|
||||
<div class="admonition abstract">
|
||||
<p class="admonition-title">Abstract</p>
|
||||
<p>Complexity analysis is like a space-time guide in the vast universe of algorithms.</p>
|
||||
<p>It leads us to explore deeply in the dimensions of time and space, in search of more elegant solutions.</p>
|
||||
<p>Complexity analysis is like a space-time navigator in the vast universe of algorithms.</p>
|
||||
<p>It guides us in exploring deeper within the the dimensions of time and space, seeking more elegant solutions.</p>
|
||||
</div>
|
||||
<h2 id="_1">本章内容<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
|
||||
<ul>
|
||||
|
|
|
@ -91,7 +91,7 @@
|
|||
<div data-md-component="skip">
|
||||
|
||||
|
||||
<a href="#22-iteration-vs-recursion" class="md-skip">
|
||||
<a href="#22-iteration-and-recursion" class="md-skip">
|
||||
Skip to content
|
||||
</a>
|
||||
|
||||
|
@ -707,9 +707,9 @@
|
|||
<ul class="md-nav__list">
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#1-for-loops" class="md-nav__link">
|
||||
<a href="#1-for-loop" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
1. For Loops
|
||||
1. for Loop
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -718,7 +718,7 @@
|
|||
<li class="md-nav__item">
|
||||
<a href="#2-while-loop" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2. While Loop
|
||||
2. while Loop
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -749,9 +749,9 @@
|
|||
<ul class="md-nav__list">
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#1-call-the-stack" class="md-nav__link">
|
||||
<a href="#1-call-stack" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
1. Call The Stack
|
||||
1. Call Stack
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -781,9 +781,9 @@
|
|||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#223-compare-the-two" class="md-nav__link">
|
||||
<a href="#223-comparison" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2.2.3 Compare The Two
|
||||
2.2.3 Comparison
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -905,9 +905,9 @@
|
|||
<ul class="md-nav__list">
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#1-for-loops" class="md-nav__link">
|
||||
<a href="#1-for-loop" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
1. For Loops
|
||||
1. for Loop
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -916,7 +916,7 @@
|
|||
<li class="md-nav__item">
|
||||
<a href="#2-while-loop" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2. While Loop
|
||||
2. while Loop
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -947,9 +947,9 @@
|
|||
<ul class="md-nav__list">
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#1-call-the-stack" class="md-nav__link">
|
||||
<a href="#1-call-stack" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
1. Call The Stack
|
||||
1. Call Stack
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -979,9 +979,9 @@
|
|||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#223-compare-the-two" class="md-nav__link">
|
||||
<a href="#223-comparison" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2.2.3 Compare The Two
|
||||
2.2.3 Comparison
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -1023,13 +1023,13 @@
|
|||
|
||||
|
||||
<!-- Page content -->
|
||||
<h1 id="22-iteration-vs-recursion">2.2 Iteration vs. Recursion<a class="headerlink" href="#22-iteration-vs-recursion" title="Permanent link">¶</a></h1>
|
||||
<p>In data structures and algorithms, it is common to repeat a task, which is closely related to the complexity of the algorithm. There are two basic program structures that we usually use to repeat a task: iteration and recursion.</p>
|
||||
<h1 id="22-iteration-and-recursion">2.2 Iteration and Recursion<a class="headerlink" href="#22-iteration-and-recursion" title="Permanent link">¶</a></h1>
|
||||
<p>In algorithms, repeatedly performing a task is common and closely related to complexity analysis. Therefore, before introducing time complexity and space complexity, let's first understand how to implement task repetition in programs, focusing on two basic programming control structures: iteration and recursion.</p>
|
||||
<h2 id="221-iteration">2.2.1 Iteration<a class="headerlink" href="#221-iteration" title="Permanent link">¶</a></h2>
|
||||
<p>An "iteration iteration" is a control structure that repeats a task. In iteration, a program repeats the execution of a piece of code until the condition is no longer satisfied.</p>
|
||||
<h3 id="1-for-loops">1. For Loops<a class="headerlink" href="#1-for-loops" title="Permanent link">¶</a></h3>
|
||||
<p><code>for</code> loops are one of the most common forms of iteration, <strong>suitable when the number of iterations is known in advance</strong>.</p>
|
||||
<p>The following function implements the summation <span class="arithmatex">\(1 + 2 + \dots + n\)</span> based on a <code>for</code> loop, and the result is recorded using the variable <code>res</code>. Note that <code>range(a, b)</code> in Python corresponds to a "left-closed-right-open" interval, which is traversed in the range <span class="arithmatex">\(a, a + 1, \dots, b-1\)</span>.</p>
|
||||
<p>"Iteration" is a control structure for repeatedly performing a task. In iteration, a program repeats a block of code as long as a certain condition is met, until this condition is no longer satisfied.</p>
|
||||
<h3 id="1-for-loop">1. for Loop<a class="headerlink" href="#1-for-loop" title="Permanent link">¶</a></h3>
|
||||
<p>The <code>for</code> loop is one of the most common forms of iteration, <strong>suitable for use when the number of iterations is known in advance</strong>.</p>
|
||||
<p>The following function implements the sum <span class="arithmatex">\(1 + 2 + \dots + n\)</span> using a <code>for</code> loop, with the sum result recorded in the variable <code>res</code>. Note that in Python, <code>range(a, b)</code> corresponds to a "left-closed, right-open" interval, covering <span class="arithmatex">\(a, a + 1, \dots, b-1\)</span>:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="1:12"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><input id="__tabbed_1_3" name="__tabbed_1" type="radio" /><input id="__tabbed_1_4" name="__tabbed_1" type="radio" /><input id="__tabbed_1_5" name="__tabbed_1" type="radio" /><input id="__tabbed_1_6" name="__tabbed_1" type="radio" /><input id="__tabbed_1_7" name="__tabbed_1" type="radio" /><input id="__tabbed_1_8" name="__tabbed_1" type="radio" /><input id="__tabbed_1_9" name="__tabbed_1" type="radio" /><input id="__tabbed_1_10" name="__tabbed_1" type="radio" /><input id="__tabbed_1_11" name="__tabbed_1" type="radio" /><input id="__tabbed_1_12" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">Python</label><label for="__tabbed_1_2">C++</label><label for="__tabbed_1_3">Java</label><label for="__tabbed_1_4">C#</label><label for="__tabbed_1_5">Go</label><label for="__tabbed_1_6">Swift</label><label for="__tabbed_1_7">JS</label><label for="__tabbed_1_8">TS</label><label for="__tabbed_1_9">Dart</label><label for="__tabbed_1_10">Rust</label><label for="__tabbed_1_11">C</label><label for="__tabbed_1_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -1176,14 +1176,14 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>The Figure 2-1 shows the flow block diagram of this summation function.</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="Flow block diagram of the summation function" class="animation-figure" src="../iteration_and_recursion.assets/iteration.png" /></a></p>
|
||||
<p align="center"> Figure 2-1 Flow block diagram of the summation function </p>
|
||||
<p>The flowchart below represents this sum function.</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="Flowchart of the Sum Function" class="animation-figure" src="../iteration_and_recursion.assets/iteration.png" /></a></p>
|
||||
<p align="center"> Figure 2-1 Flowchart of the Sum Function </p>
|
||||
|
||||
<p>The number of operations in this summation function is proportional to the size of the input data <span class="arithmatex">\(n\)</span>, or a "linear relationship". In fact, <strong>time complexity describes this "linear relationship"</strong>. This is described in more detail in the next section.</p>
|
||||
<h3 id="2-while-loop">2. While Loop<a class="headerlink" href="#2-while-loop" title="Permanent link">¶</a></h3>
|
||||
<p>Similar to a <code>for</code> loop, a <code>while</code> loop is a way to implement iteration. In a <code>while</code> loop, the program first checks the condition at each turn, and if the condition is true, it continues, otherwise it ends the loop.</p>
|
||||
<p>Below, we use a <code>while</code> loop to realize the summation <span class="arithmatex">\(1 + 2 + \dots + n\)</span> .</p>
|
||||
<p>The number of operations in this sum function is proportional to the input data size <span class="arithmatex">\(n\)</span>, or in other words, it has a "linear relationship". This is actually what <strong>time complexity describes</strong>. This topic will be detailed in the next section.</p>
|
||||
<h3 id="2-while-loop">2. while Loop<a class="headerlink" href="#2-while-loop" title="Permanent link">¶</a></h3>
|
||||
<p>Similar to the <code>for</code> loop, the <code>while</code> loop is another method to implement iteration. In a <code>while</code> loop, the program checks the condition in each round; if the condition is true, it continues, otherwise, the loop ends.</p>
|
||||
<p>Below we use a <code>while</code> loop to implement the sum <span class="arithmatex">\(1 + 2 + \dots + n\)</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">Python</label><label for="__tabbed_2_2">C++</label><label for="__tabbed_2_3">Java</label><label for="__tabbed_2_4">C#</label><label for="__tabbed_2_5">Go</label><label for="__tabbed_2_6">Swift</label><label for="__tabbed_2_7">JS</label><label for="__tabbed_2_8">TS</label><label for="__tabbed_2_9">Dart</label><label for="__tabbed_2_10">Rust</label><label for="__tabbed_2_11">C</label><label for="__tabbed_2_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -1356,8 +1356,8 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>In <code>while</code> loops, since the steps of initializing and updating condition variables are independent of the loop structure, <strong>it has more degrees of freedom than <code>for</code> loops</strong>.</p>
|
||||
<p>For example, in the following code, the condition variable <span class="arithmatex">\(i\)</span> is updated twice per round, which is not convenient to implement with a <code>for</code> loop.</p>
|
||||
<p><strong>The <code>while</code> loop is more flexible than the <code>for</code> loop</strong>. In a <code>while</code> loop, we can freely design the initialization and update steps of the condition variable.</p>
|
||||
<p>For example, in the following code, the condition variable <span class="arithmatex">\(i\)</span> is updated twice in each round, which would be inconvenient to implement with a <code>for</code> loop:</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>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -1553,9 +1553,9 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>Overall, <strong><code>for</code> loops have more compact code and <code>while</code> loops are more flexible</strong>, and both can implement iteration structures. The choice of which one to use should be based on the needs of the particular problem.</p>
|
||||
<p>Overall, <strong><code>for</code> loops are more concise, while <code>while</code> loops are more flexible</strong>. Both can implement iterative structures. Which one to use should be determined based on the specific requirements of the problem.</p>
|
||||
<h3 id="3-nested-loops">3. Nested Loops<a class="headerlink" href="#3-nested-loops" title="Permanent link">¶</a></h3>
|
||||
<p>We can nest one loop structure inside another, using the <code>for</code> loop as an example:</p>
|
||||
<p>We can nest one loop structure within another. Below is an example using <code>for</code> loops:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="4:12"><input checked="checked" id="__tabbed_4_1" name="__tabbed_4" type="radio" /><input id="__tabbed_4_2" name="__tabbed_4" type="radio" /><input id="__tabbed_4_3" name="__tabbed_4" type="radio" /><input id="__tabbed_4_4" name="__tabbed_4" type="radio" /><input id="__tabbed_4_5" name="__tabbed_4" type="radio" /><input id="__tabbed_4_6" name="__tabbed_4" type="radio" /><input id="__tabbed_4_7" name="__tabbed_4" type="radio" /><input id="__tabbed_4_8" name="__tabbed_4" type="radio" /><input id="__tabbed_4_9" name="__tabbed_4" type="radio" /><input id="__tabbed_4_10" name="__tabbed_4" type="radio" /><input id="__tabbed_4_11" name="__tabbed_4" type="radio" /><input id="__tabbed_4_12" name="__tabbed_4" type="radio" /><div class="tabbed-labels"><label for="__tabbed_4_1">Python</label><label for="__tabbed_4_2">C++</label><label for="__tabbed_4_3">Java</label><label for="__tabbed_4_4">C#</label><label for="__tabbed_4_5">Go</label><label for="__tabbed_4_6">Swift</label><label for="__tabbed_4_7">JS</label><label for="__tabbed_4_8">TS</label><label for="__tabbed_4_9">Dart</label><label for="__tabbed_4_10">Rust</label><label for="__tabbed_4_11">C</label><label for="__tabbed_4_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -1744,25 +1744,25 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>The Figure 2-2 gives the block diagram of the flow of this nested loop.</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="Block diagram of the flow of nested loops" class="animation-figure" src="../iteration_and_recursion.assets/nested_iteration.png" /></a></p>
|
||||
<p align="center"> Figure 2-2 Block diagram of the flow of nested loops </p>
|
||||
<p>The flowchart below represents this nested loop.</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="Flowchart of the Nested Loop" class="animation-figure" src="../iteration_and_recursion.assets/nested_iteration.png" /></a></p>
|
||||
<p align="center"> Figure 2-2 Flowchart of the Nested Loop </p>
|
||||
|
||||
<p>In this case, the number of operations of the function is proportional to <span class="arithmatex">\(n^2\)</span>, or the algorithm's running time is "squared" to the size of the input data <span class="arithmatex">\(n\)</span>.</p>
|
||||
<p>We can continue to add nested loops, and each nest is a "dimension up", which will increase the time complexity to "cubic relations", "quadratic relations", and so on.</p>
|
||||
<p>In this case, the number of operations in the function is proportional to <span class="arithmatex">\(n^2\)</span>, or the algorithm's running time and the input data size <span class="arithmatex">\(n\)</span> have a "quadratic relationship".</p>
|
||||
<p>We can continue adding nested loops, each nesting is a "dimensional escalation," which will increase the time complexity to "cubic," "quartic," and so on.</p>
|
||||
<h2 id="222-recursion">2.2.2 Recursion<a class="headerlink" href="#222-recursion" title="Permanent link">¶</a></h2>
|
||||
<p>"Recursion recursion is an algorithmic strategy to solve a problem by calling the function itself. It consists of two main phases.</p>
|
||||
<p>"Recursion" is an algorithmic strategy that solves problems by having a function call itself. It mainly consists of two phases.</p>
|
||||
<ol>
|
||||
<li><strong>recursive</strong>: the program calls itself deeper and deeper, usually passing smaller or simpler arguments, until a "termination condition" is reached.</li>
|
||||
<li><strong>Recursion</strong>: After the "termination condition" is triggered, the program returns from the deepest level of the recursion function, level by level, aggregating the results of each level.</li>
|
||||
<li><strong>Recursion</strong>: The program continuously calls itself, usually with smaller or more simplified parameters, until reaching a "termination condition."</li>
|
||||
<li><strong>Return</strong>: Upon triggering the "termination condition," the program begins to return from the deepest recursive function, aggregating the results of each layer.</li>
|
||||
</ol>
|
||||
<p>And from an implementation point of view, recursion code contains three main elements.</p>
|
||||
<p>From an implementation perspective, recursive code mainly includes three elements.</p>
|
||||
<ol>
|
||||
<li><strong>Termination condition</strong>: used to decide when to switch from "recursive" to "inductive".</li>
|
||||
<li><strong>Recursion call</strong>: corresponds to "recursion", where the function calls itself, usually with smaller or more simplified input parameters.</li>
|
||||
<li><strong>return result</strong>: corresponds to "return", returning the result of the current recursion level to the previous one.</li>
|
||||
<li><strong>Termination Condition</strong>: Determines when to switch from "recursion" to "return."</li>
|
||||
<li><strong>Recursive Call</strong>: Corresponds to "recursion," where the function calls itself, usually with smaller or more simplified parameters.</li>
|
||||
<li><strong>Return Result</strong>: Corresponds to "return," where the result of the current recursion level is returned to the previous layer.</li>
|
||||
</ol>
|
||||
<p>Observe the following code, we only need to call the function <code>recur(n)</code> , and the calculation of <span class="arithmatex">\(1 + 2 + \dots + n\)</span> is done:</p>
|
||||
<p>Observe the following code, where calling the function <code>recur(n)</code> completes the computation of <span class="arithmatex">\(1 + 2 + \dots + n\)</span>:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="5:12"><input checked="checked" id="__tabbed_5_1" name="__tabbed_5" type="radio" /><input id="__tabbed_5_2" name="__tabbed_5" type="radio" /><input id="__tabbed_5_3" name="__tabbed_5" type="radio" /><input id="__tabbed_5_4" name="__tabbed_5" type="radio" /><input id="__tabbed_5_5" name="__tabbed_5" type="radio" /><input id="__tabbed_5_6" name="__tabbed_5" type="radio" /><input id="__tabbed_5_7" name="__tabbed_5" type="radio" /><input id="__tabbed_5_8" name="__tabbed_5" type="radio" /><input id="__tabbed_5_9" name="__tabbed_5" type="radio" /><input id="__tabbed_5_10" name="__tabbed_5" type="radio" /><input id="__tabbed_5_11" name="__tabbed_5" type="radio" /><input id="__tabbed_5_12" name="__tabbed_5" type="radio" /><div class="tabbed-labels"><label for="__tabbed_5_1">Python</label><label for="__tabbed_5_2">C++</label><label for="__tabbed_5_3">Java</label><label for="__tabbed_5_4">C#</label><label for="__tabbed_5_5">Go</label><label for="__tabbed_5_6">Swift</label><label for="__tabbed_5_7">JS</label><label for="__tabbed_5_8">TS</label><label for="__tabbed_5_9">Dart</label><label for="__tabbed_5_10">Rust</label><label for="__tabbed_5_11">C</label><label for="__tabbed_5_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -1923,38 +1923,38 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>The Figure 2-3 shows the recursion of the function.</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="Recursion process for the summation function" class="animation-figure" src="../iteration_and_recursion.assets/recursion_sum.png" /></a></p>
|
||||
<p align="center"> Figure 2-3 Recursion process for the summation function </p>
|
||||
<p>The Figure 2-3 shows the recursive process of this function.</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="Recursive Process of the Sum Function" class="animation-figure" src="../iteration_and_recursion.assets/recursion_sum.png" /></a></p>
|
||||
<p align="center"> Figure 2-3 Recursive Process of the Sum Function </p>
|
||||
|
||||
<p>Although iteration and recursion can yield the same results from a computational point of view, <strong>they represent two completely different paradigms for thinking about and solving problems</strong>.</p>
|
||||
<p>Although iteration and recursion can achieve the same results from a computational standpoint, <strong>they represent two entirely different paradigms of thinking and solving problems</strong>.</p>
|
||||
<ul>
|
||||
<li><strong>Iteration</strong>: solving problems "from the bottom up". Start with the most basic steps and repeat or add to them until the task is completed.</li>
|
||||
<li><strong>Recursion</strong>: solving problems "from the top down". The original problem is broken down into smaller subproblems that have the same form as the original problem. Next, the subproblem continues to be broken down into smaller subproblems until it stops at the base case (the solution to the base case is known).</li>
|
||||
<li><strong>Iteration</strong>: Solves problems "from the bottom up." It starts with the most basic steps, then repeatedly adds or accumulates these steps until the task is complete.</li>
|
||||
<li><strong>Recursion</strong>: Solves problems "from the top down." It breaks down the original problem into smaller sub-problems, each of which has the same form as the original problem. These sub-problems are then further decomposed into even smaller sub-problems, stopping at the base case (whose solution is known).</li>
|
||||
</ul>
|
||||
<p>As an example of the above summation function, set the problem <span class="arithmatex">\(f(n) = 1 + 2 + \dots + n\)</span> .</p>
|
||||
<p>Taking the sum function as an example, let's define the problem as <span class="arithmatex">\(f(n) = 1 + 2 + \dots + n\)</span>.</p>
|
||||
<ul>
|
||||
<li><strong>Iteration</strong>: the summation process is simulated in a loop, iterating from <span class="arithmatex">\(1\)</span> to <span class="arithmatex">\(n\)</span> and executing the summation operation in each round to find <span class="arithmatex">\(f(n)\)</span>.</li>
|
||||
<li><strong>Recursion</strong>: decompose the problem into subproblems <span class="arithmatex">\(f(n) = n + f(n-1)\)</span> and keep (recursively) decomposing until the base case <span class="arithmatex">\(f(1) = 1\)</span> terminates.</li>
|
||||
<li><strong>Iteration</strong>: In a loop, simulate the summing process, iterating from <span class="arithmatex">\(1\)</span> to <span class="arithmatex">\(n\)</span>, performing the sum operation in each round, to obtain <span class="arithmatex">\(f(n)\)</span>.</li>
|
||||
<li><strong>Recursion</strong>: Break down the problem into sub-problems <span class="arithmatex">\(f(n) = n + f(n-1)\)</span>, continuously (recursively) decomposing until reaching the base case <span class="arithmatex">\(f(1) = 1\)</span> and then stopping.</li>
|
||||
</ul>
|
||||
<h3 id="1-call-the-stack">1. Call The Stack<a class="headerlink" href="#1-call-the-stack" title="Permanent link">¶</a></h3>
|
||||
<p>Each time a recursion function calls itself, the system allocates memory for the newly opened function to store local variables, call addresses, other information, and so on. This results in two things.</p>
|
||||
<h3 id="1-call-stack">1. Call Stack<a class="headerlink" href="#1-call-stack" title="Permanent link">¶</a></h3>
|
||||
<p>Each time a recursive function calls itself, the system allocates memory for the newly initiated function to store local variables, call addresses, and other information. This leads to two main consequences.</p>
|
||||
<ul>
|
||||
<li>The context data for a function is stored in an area of memory called "stack frame space" and is not freed until the function returns. As a result, <strong>recursion is usually more memory-intensive than iteration</strong>.</li>
|
||||
<li>Recursion calls to functions incur additional overhead. <strong>Therefore recursion is usually less time efficient than loops</strong>.</li>
|
||||
<li>The function's context data is stored in a memory area called "stack frame space" and is only released after the function returns. Therefore, <strong>recursion generally consumes more memory space than iteration</strong>.</li>
|
||||
<li>Recursive calls introduce additional overhead. <strong>Hence, recursion is usually less time-efficient than loops</strong>.</li>
|
||||
</ul>
|
||||
<p>As shown in the Figure 2-4 , before the termination condition is triggered, there are <span class="arithmatex">\(n\)</span> unreturned recursion functions at the same time, <strong>with a recursion depth of <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="Recursion call depth" class="animation-figure" src="../iteration_and_recursion.assets/recursion_sum_depth.png" /></a></p>
|
||||
<p align="center"> Figure 2-4 Recursion call depth </p>
|
||||
<p>As shown in the Figure 2-4 , there are <span class="arithmatex">\(n\)</span> unreturned recursive functions before triggering the termination condition, indicating a <strong>recursion depth of <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="Recursion Call Depth" class="animation-figure" src="../iteration_and_recursion.assets/recursion_sum_depth.png" /></a></p>
|
||||
<p align="center"> Figure 2-4 Recursion Call Depth </p>
|
||||
|
||||
<p>In practice, the depth of recursion allowed by a programming language is usually limited, and too deep a recursion may result in a stack overflow error.</p>
|
||||
<p>In practice, the depth of recursion allowed by programming languages is usually limited, and excessively deep recursion can lead to stack overflow errors.</p>
|
||||
<h3 id="2-tail-recursion">2. Tail Recursion<a class="headerlink" href="#2-tail-recursion" title="Permanent link">¶</a></h3>
|
||||
<p>Interestingly, <strong>if a function makes a recursion call only at the last step before returning</strong>, the function can be optimized by the compiler or interpreter to be comparable to iteration in terms of space efficiency. This situation is called "tail recursion tail recursion".</p>
|
||||
<p>Interestingly, <strong>if a function makes its recursive call as the last step before returning</strong>, it can be optimized by compilers or interpreters to be as space-efficient as iteration. This scenario is known as "tail recursion".</p>
|
||||
<ul>
|
||||
<li><strong>Ordinary recursion</strong>: when a function returns to a function at a higher level, it needs to continue executing the code, so the system needs to save the context of the previous call.</li>
|
||||
<li><strong>tail recursion</strong>: the recursion call is the last operation before the function returns, which means that the function does not need to continue with other operations after returning to the previous level, so the system does not need to save the context of the previous function.</li>
|
||||
<li><strong>Regular Recursion</strong>: The function needs to perform more code after returning to the previous level, so the system needs to save the context of the previous call.</li>
|
||||
<li><strong>Tail Recursion</strong>: The recursive call is the last operation before the function returns, meaning no further actions are required upon returning to the previous level, so the system doesn't need to save the context of the previous level's function.</li>
|
||||
</ul>
|
||||
<p>In the case of calculating <span class="arithmatex">\(1 + 2 + \dots + n\)</span>, for example, we can implement tail recursion by setting the result variable <code>res</code> as a function parameter.</p>
|
||||
<p>For example, in calculating <span class="arithmatex">\(1 + 2 + \dots + n\)</span>, we can make the result variable <code>res</code> a parameter of the function, thereby achieving tail recursion:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="6:12"><input checked="checked" id="__tabbed_6_1" name="__tabbed_6" type="radio" /><input id="__tabbed_6_2" name="__tabbed_6" type="radio" /><input id="__tabbed_6_3" name="__tabbed_6" type="radio" /><input id="__tabbed_6_4" name="__tabbed_6" type="radio" /><input id="__tabbed_6_5" name="__tabbed_6" type="radio" /><input id="__tabbed_6_6" name="__tabbed_6" type="radio" /><input id="__tabbed_6_7" name="__tabbed_6" type="radio" /><input id="__tabbed_6_8" name="__tabbed_6" type="radio" /><input id="__tabbed_6_9" name="__tabbed_6" type="radio" /><input id="__tabbed_6_10" name="__tabbed_6" type="radio" /><input id="__tabbed_6_11" name="__tabbed_6" type="radio" /><input id="__tabbed_6_12" name="__tabbed_6" type="radio" /><div class="tabbed-labels"><label for="__tabbed_6_1">Python</label><label for="__tabbed_6_2">C++</label><label for="__tabbed_6_3">Java</label><label for="__tabbed_6_4">C#</label><label for="__tabbed_6_5">Go</label><label for="__tabbed_6_6">Swift</label><label for="__tabbed_6_7">JS</label><label for="__tabbed_6_8">TS</label><label for="__tabbed_6_9">Dart</label><label for="__tabbed_6_10">Rust</label><label for="__tabbed_6_11">C</label><label for="__tabbed_6_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -2091,30 +2091,30 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>The execution of tail recursion is shown in the Figure 2-5 . Comparing normal recursion and tail recursion, the execution point of the summation operation is different.</p>
|
||||
<p>The execution process of tail recursion is shown in the following figure. Comparing regular recursion and tail recursion, the point of the summation operation is different.</p>
|
||||
<ul>
|
||||
<li><strong>Ordinary recursion</strong>: the summing operation is performed during the "return" process, and the summing operation is performed again after returning from each level.</li>
|
||||
<li><strong>Tail recursion</strong>: the summing operation is performed in a "recursion" process, the "recursion" process simply returns in levels.</li>
|
||||
<li><strong>Regular Recursion</strong>: The summation operation occurs during the "return" phase, requiring another summation after each layer returns.</li>
|
||||
<li><strong>Tail Recursion</strong>: The summation operation occurs during the "recursion" phase, and the "return" phase only involves returning through each layer.</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="tail recursion process" class="animation-figure" src="../iteration_and_recursion.assets/tail_recursion_sum.png" /></a></p>
|
||||
<p align="center"> Figure 2-5 tail recursion process </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="Tail Recursion Process" class="animation-figure" src="../iteration_and_recursion.assets/tail_recursion_sum.png" /></a></p>
|
||||
<p align="center"> Figure 2-5 Tail Recursion Process </p>
|
||||
|
||||
<div class="admonition tip">
|
||||
<p class="admonition-title">Tip</p>
|
||||
<p>Note that many compilers or interpreters do not support tail recursion optimization. For example, Python does not support tail recursion optimization by default, so even if a function is tail recursive, you may still encounter stack overflow problems.</p>
|
||||
<p>Note that many compilers or interpreters do not support tail recursion optimization. For example, Python does not support tail recursion optimization by default, so even if the function is in the form of tail recursion, it may still encounter stack overflow issues.</p>
|
||||
</div>
|
||||
<h3 id="3-recursion-tree">3. Recursion Tree<a class="headerlink" href="#3-recursion-tree" title="Permanent link">¶</a></h3>
|
||||
<p>When dealing with algorithmic problems related to divide and conquer, recursion is often more intuitive and easier to read than iteration. Take the Fibonacci sequence as an example.</p>
|
||||
<p>When dealing with algorithms related to "divide and conquer", recursion often offers a more intuitive approach and more readable code than iteration. Take the "Fibonacci sequence" as an example.</p>
|
||||
<div class="admonition question">
|
||||
<p class="admonition-title">Question</p>
|
||||
<p>Given a Fibonacci series <span class="arithmatex">\(0, 1, 1, 2, 3, 5, 8, 13, \dots\)</span> , find the <span class="arithmatex">\(n\)</span>th number of the series.</p>
|
||||
<p>Given a Fibonacci sequence <span class="arithmatex">\(0, 1, 1, 2, 3, 5, 8, 13, \dots\)</span>, find the <span class="arithmatex">\(n\)</span>th number in the sequence.</p>
|
||||
</div>
|
||||
<p>Let the <span class="arithmatex">\(n\)</span>th number of the Fibonacci series be <span class="arithmatex">\(f(n)\)</span> , which leads to two easy conclusions.</p>
|
||||
<p>Let the <span class="arithmatex">\(n\)</span>th number of the Fibonacci sequence be <span class="arithmatex">\(f(n)\)</span>, it's easy to deduce two conclusions:</p>
|
||||
<ul>
|
||||
<li>The first two numbers of the series are <span class="arithmatex">\(f(1) = 0\)</span> and <span class="arithmatex">\(f(2) = 1\)</span>.</li>
|
||||
<li>Each number in the series is the sum of the previous two numbers, i.e. <span class="arithmatex">\(f(n) = f(n - 1) + f(n - 2)\)</span> .</li>
|
||||
<li>The first two numbers of the sequence are <span class="arithmatex">\(f(1) = 0\)</span> and <span class="arithmatex">\(f(2) = 1\)</span>.</li>
|
||||
<li>Each number in the sequence is the sum of the two preceding ones, that is, <span class="arithmatex">\(f(n) = f(n - 1) + f(n - 2)\)</span>.</li>
|
||||
</ul>
|
||||
<p>Recursion code can be written by making recursion calls according to the recursion relationship, using the first two numbers as termination conditions. Call <code>fib(n)</code> to get the <span class="arithmatex">\(n\)</span>th number of the Fibonacci series.</p>
|
||||
<p>Using the recursive relation, and considering the first two numbers as termination conditions, we can write the recursive code. Calling <code>fib(n)</code> will yield the <span class="arithmatex">\(n\)</span>th number of the Fibonacci sequence:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="7:12"><input checked="checked" id="__tabbed_7_1" name="__tabbed_7" type="radio" /><input id="__tabbed_7_2" name="__tabbed_7" type="radio" /><input id="__tabbed_7_3" name="__tabbed_7" type="radio" /><input id="__tabbed_7_4" name="__tabbed_7" type="radio" /><input id="__tabbed_7_5" name="__tabbed_7" type="radio" /><input id="__tabbed_7_6" name="__tabbed_7" type="radio" /><input id="__tabbed_7_7" name="__tabbed_7" type="radio" /><input id="__tabbed_7_8" name="__tabbed_7" type="radio" /><input id="__tabbed_7_9" name="__tabbed_7" type="radio" /><input id="__tabbed_7_10" name="__tabbed_7" type="radio" /><input id="__tabbed_7_11" name="__tabbed_7" type="radio" /><input id="__tabbed_7_12" name="__tabbed_7" type="radio" /><div class="tabbed-labels"><label for="__tabbed_7_1">Python</label><label for="__tabbed_7_2">C++</label><label for="__tabbed_7_3">Java</label><label for="__tabbed_7_4">C#</label><label for="__tabbed_7_5">Go</label><label for="__tabbed_7_6">Swift</label><label for="__tabbed_7_7">JS</label><label for="__tabbed_7_8">TS</label><label for="__tabbed_7_9">Dart</label><label for="__tabbed_7_10">Rust</label><label for="__tabbed_7_11">C</label><label for="__tabbed_7_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -2275,63 +2275,63 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>Looking at the above code, we have recursively called two functions within a function, <strong>this means that from one call, two call branches are created</strong>. As shown in the Figure 2-6 , this recursion will result in a recursion tree with the number of levels <span class="arithmatex">\(n\)</span>.</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="Recursion tree for Fibonacci series" class="animation-figure" src="../iteration_and_recursion.assets/recursion_tree.png" /></a></p>
|
||||
<p align="center"> Figure 2-6 Recursion tree for Fibonacci series </p>
|
||||
<p>Observing the above code, we see that it recursively calls two functions within itself, <strong>meaning that one call generates two branching calls</strong>. As illustrated below, this continuous recursive calling eventually creates a "recursion tree" with a depth of <span class="arithmatex">\(n\)</span>.</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="Fibonacci Sequence Recursion Tree" class="animation-figure" src="../iteration_and_recursion.assets/recursion_tree.png" /></a></p>
|
||||
<p align="center"> Figure 2-6 Fibonacci Sequence Recursion Tree </p>
|
||||
|
||||
<p>Essentially, recursion embodies the paradigm of "breaking down a problem into smaller sub-problems", and this divide and conquer strategy is essential.</p>
|
||||
<p>Fundamentally, recursion embodies the paradigm of "breaking down a problem into smaller sub-problems." This divide-and-conquer strategy is crucial.</p>
|
||||
<ul>
|
||||
<li>From an algorithmic point of view, many important algorithmic strategies such as searching, sorting algorithm, backtracking, divide and conquer, dynamic programming, etc. directly or indirectly apply this way of thinking.</li>
|
||||
<li>From a data structure point of view, recursion is naturally suited to problems related to linked lists, trees and graphs because they are well suited to be analyzed with the idea of partitioning.</li>
|
||||
<li>From an algorithmic perspective, many important strategies like searching, sorting, backtracking, divide-and-conquer, and dynamic programming directly or indirectly use this way of thinking.</li>
|
||||
<li>From a data structure perspective, recursion is naturally suited for dealing with linked lists, trees, and graphs, as they are well suited for analysis using the divide-and-conquer approach.</li>
|
||||
</ul>
|
||||
<h2 id="223-compare-the-two">2.2.3 Compare The Two<a class="headerlink" href="#223-compare-the-two" title="Permanent link">¶</a></h2>
|
||||
<p>To summarize the above, as shown in the Table 2-1 , iteration and recursion differ in implementation, performance and applicability.</p>
|
||||
<p align="center"> Table 2-1 Comparison of iteration and recursion features </p>
|
||||
<h2 id="223-comparison">2.2.3 Comparison<a class="headerlink" href="#223-comparison" title="Permanent link">¶</a></h2>
|
||||
<p>Summarizing the above content, the following table shows the differences between iteration and recursion in terms of implementation, performance, and applicability.</p>
|
||||
<p align="center"> Table: Comparison of Iteration and Recursion Characteristics </p>
|
||||
|
||||
<div class="center-table">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>iteration</th>
|
||||
<th>recursion</th>
|
||||
<th>Iteration</th>
|
||||
<th>Recursion</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>implementation</td>
|
||||
<td>circular structure</td>
|
||||
<td>function call itself</td>
|
||||
<td>Approach</td>
|
||||
<td>Loop structure</td>
|
||||
<td>Function calls itself</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>time-efficient</td>
|
||||
<td>typically efficient, no function call overhead</td>
|
||||
<td>overhead on every function call</td>
|
||||
<td>Time Efficiency</td>
|
||||
<td>Generally higher efficiency, no function call overhead</td>
|
||||
<td>Each function call generates overhead</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Memory Usage</td>
|
||||
<td>Usually uses a fixed size of memory space</td>
|
||||
<td>Cumulative function calls may use a lot of stack frame space</td>
|
||||
<td>Typically uses a fixed size of memory space</td>
|
||||
<td>Accumulative function calls can use a substantial amount of stack frame space</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Applicable Problems</td>
|
||||
<td>For simple cyclic tasks, code is intuitive and readable</td>
|
||||
<td>For sub-problem decomposition, such as trees, graphs, divide and conquer, backtracking, etc., the code structure is concise and clear</td>
|
||||
<td>Suitable Problems</td>
|
||||
<td>Suitable for simple loop tasks, intuitive and readable code</td>
|
||||
<td>Suitable for problem decomposition, like trees, graphs, divide-and-conquer, backtracking, etc., concise and clear code structure</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="admonition tip">
|
||||
<p class="admonition-title">Tip</p>
|
||||
<p>If you find the following solutions difficult to understand, you can review them after reading the "Stack" chapter.</p>
|
||||
<p>If you find the following content difficult to understand, consider revisiting it after reading the "Stack" chapter.</p>
|
||||
</div>
|
||||
<p>So what is the intrinsic connection between iteration and recursion? In the case of the recursive function described above, the summing operation takes place in the "return" phase of the recursion. This means that the function that is initially called is actually the last to complete its summing operation, <strong>This mechanism works in the same way as the stack's "first in, last out" principle</strong>.</p>
|
||||
<p>In fact, recursion terms like "call stack" and "stack frame space" already imply a close relationship between recursion and the stack.</p>
|
||||
<p>So, what is the intrinsic connection between iteration and recursion? Taking the above recursive function as an example, the summation operation occurs during the recursion's "return" phase. This means that the initially called function is actually the last to complete its summation operation, <strong>mirroring the "last in, first out" principle of a stack</strong>.</p>
|
||||
<p>In fact, recursive terms like "call stack" and "stack frame space" hint at the close relationship between recursion and stacks.</p>
|
||||
<ol>
|
||||
<li><strong>Recursive</strong>: When a function is called, the system allocates a new stack frame on the "call stack" for the function, which is used to store the function's local variables, parameters, return address, and other data.</li>
|
||||
<li><strong>Return to</strong>: When a function completes execution and returns, the corresponding stack frame is removed from the "call stack", restoring the function's previous execution environment.</li>
|
||||
<li><strong>Recursion</strong>: When a function is called, the system allocates a new stack frame on the "call stack" for that function, storing local variables, parameters, return addresses, and other data.</li>
|
||||
<li><strong>Return</strong>: When a function completes execution and returns, the corresponding stack frame is removed from the "call stack," restoring the execution environment of the previous function.</li>
|
||||
</ol>
|
||||
<p>Thus, <strong>we can use an explicit stack to model the behavior of the call stack</strong>, thus transforming recursion into an iteration form:</p>
|
||||
<p>Therefore, <strong>we can use an explicit stack to simulate the behavior of the call stack</strong>, thus transforming recursion into an iterative form:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="8:12"><input checked="checked" id="__tabbed_8_1" name="__tabbed_8" type="radio" /><input id="__tabbed_8_2" name="__tabbed_8" type="radio" /><input id="__tabbed_8_3" name="__tabbed_8" type="radio" /><input id="__tabbed_8_4" name="__tabbed_8" type="radio" /><input id="__tabbed_8_5" name="__tabbed_8" type="radio" /><input id="__tabbed_8_6" name="__tabbed_8" type="radio" /><input id="__tabbed_8_7" name="__tabbed_8" type="radio" /><input id="__tabbed_8_8" name="__tabbed_8" type="radio" /><input id="__tabbed_8_9" name="__tabbed_8" type="radio" /><input id="__tabbed_8_10" name="__tabbed_8" type="radio" /><input id="__tabbed_8_11" name="__tabbed_8" type="radio" /><input id="__tabbed_8_12" name="__tabbed_8" type="radio" /><div class="tabbed-labels"><label for="__tabbed_8_1">Python</label><label for="__tabbed_8_2">C++</label><label for="__tabbed_8_3">Java</label><label for="__tabbed_8_4">C#</label><label for="__tabbed_8_5">Go</label><label for="__tabbed_8_6">Swift</label><label for="__tabbed_8_7">JS</label><label for="__tabbed_8_8">TS</label><label for="__tabbed_8_9">Dart</label><label for="__tabbed_8_10">Rust</label><label for="__tabbed_8_11">C</label><label for="__tabbed_8_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -2589,12 +2589,12 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>Observing the code above, it becomes more complex when recursion is converted to iteration. Although iteration and recursion can be converted to each other in many cases, it is not always worth doing so for two reasons.</p>
|
||||
<p>Observing the above code, when recursion is transformed into iteration, the code becomes more complex. Although iteration and recursion can often be transformed into each other, it's not always advisable to do so for two reasons:</p>
|
||||
<ul>
|
||||
<li>The transformed code may be more difficult to understand and less readable.</li>
|
||||
<li>For some complex problems, simulating the behavior of the system call stack can be very difficult.</li>
|
||||
<li>The transformed code may become harder to understand and less readable.</li>
|
||||
<li>For some complex problems, simulating the behavior of the system's call stack can be quite challenging.</li>
|
||||
</ul>
|
||||
<p>In short, <strong>the choice of iteration or recursion depends on the nature of the particular problem</strong>. In programming practice, it is crucial to weigh the advantages and disadvantages of both and choose the appropriate method based on the context.</p>
|
||||
<p>In summary, <strong>choosing between iteration and recursion depends on the nature of the specific problem</strong>. In programming practice, weighing the pros and cons of each and choosing the appropriate method for the situation is essential.</p>
|
||||
|
||||
<!-- Source file information -->
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@
|
|||
<div data-md-component="skip">
|
||||
|
||||
|
||||
<a href="#21-evaluation-of-algorithm-efficiency" class="md-skip">
|
||||
<a href="#21-algorithm-efficiency-assessment" class="md-skip">
|
||||
Skip to content
|
||||
</a>
|
||||
|
||||
|
@ -676,9 +676,9 @@
|
|||
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#211-practical-testing" class="md-nav__link">
|
||||
<a href="#211-actual-testing" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2.1.1 Practical Testing
|
||||
2.1.1 Actual Testing
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -820,9 +820,9 @@
|
|||
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#211-practical-testing" class="md-nav__link">
|
||||
<a href="#211-actual-testing" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2.1.1 Practical Testing
|
||||
2.1.1 Actual Testing
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -873,43 +873,43 @@
|
|||
|
||||
|
||||
<!-- Page content -->
|
||||
<h1 id="21-evaluation-of-algorithm-efficiency">2.1 Evaluation Of Algorithm Efficiency<a class="headerlink" href="#21-evaluation-of-algorithm-efficiency" title="Permanent link">¶</a></h1>
|
||||
<p>In algorithm design, we aim to achieve two goals in succession:</p>
|
||||
<h1 id="21-algorithm-efficiency-assessment">2.1 Algorithm Efficiency Assessment<a class="headerlink" href="#21-algorithm-efficiency-assessment" title="Permanent link">¶</a></h1>
|
||||
<p>In algorithm design, we pursue the following two objectives in sequence.</p>
|
||||
<ol>
|
||||
<li><strong>Finding a Solution to the Problem</strong>: The algorithm needs to reliably find the correct solution within the specified input range.</li>
|
||||
<li><strong>Seeking the Optimal Solution</strong>: There may be multiple ways to solve the same problem, and our goal is to find the most efficient algorithm possible.</li>
|
||||
<li><strong>Finding a Solution to the Problem</strong>: The algorithm should reliably find the correct solution within the stipulated range of inputs.</li>
|
||||
<li><strong>Seeking the Optimal Solution</strong>: For the same problem, multiple solutions might exist, and we aim to find the most efficient algorithm possible.</li>
|
||||
</ol>
|
||||
<p>In other words, once the ability to solve the problem is established, the efficiency of the algorithm emerges as the main benchmark for assessing its quality, which includes the following two aspects.</p>
|
||||
<p>In other words, under the premise of being able to solve the problem, algorithm efficiency has become the main criterion for evaluating the merits of an algorithm, which includes the following two dimensions.</p>
|
||||
<ul>
|
||||
<li><strong>Time Efficiency</strong>: The speed at which an algorithm runs.</li>
|
||||
<li><strong>Space Efficiency</strong>: The amount of memory space the algorithm consumes.</li>
|
||||
<li><strong>Space Efficiency</strong>: The size of the memory space occupied by an algorithm.</li>
|
||||
</ul>
|
||||
<p>In short, our goal is to design data structures and algorithms that are both "fast and economical". Effectively evaluating algorithm efficiency is crucial, as it allows for the comparison of different algorithms and guides the design and optimization process.</p>
|
||||
<p>There are mainly two approaches for assessing efficiency: practical testing and theoretical estimation.</p>
|
||||
<h2 id="211-practical-testing">2.1.1 Practical Testing<a class="headerlink" href="#211-practical-testing" title="Permanent link">¶</a></h2>
|
||||
<p>Let's consider a scenario where we have two algorithms, <code>A</code> and <code>B</code>, both capable of solving the same problem. To compare their efficiency, the most direct method is to use a computer to run both algorithms while monitoring and recording their execution time and memory usage. This approach provides a realistic assessment of their performance, but it also has significant limitations.</p>
|
||||
<p>On one hand, it's challenging to eliminate the interference of the test environment. Hardware configurations can significantly affect the performance of algorithms. For instance, on one computer, Algorithm <code>A</code> might run faster than Algorithm <code>B</code>, but the results could be the opposite on another computer with different specifications. This means we would need to conduct tests on a variety of machines and calculate an average efficiency, which is impractical.</p>
|
||||
<p>Furthermore, conducting comprehensive tests is resource-intensive. The efficiency of algorithms can vary with different volumes of input data. For example, with smaller data sets, Algorithm A might run faster than Algorithm B; however, this could change with larger data sets. Therefore, to reach a convincing conclusion, it's necessary to test a range of data sizes, which requires excessive computational resources.</p>
|
||||
<p>In short, <strong>our goal is to design data structures and algorithms that are both fast and memory-efficient</strong>. Effectively assessing algorithm efficiency is crucial because only then can we compare various algorithms and guide the process of algorithm design and optimization.</p>
|
||||
<p>There are mainly two methods of efficiency assessment: actual testing and theoretical estimation.</p>
|
||||
<h2 id="211-actual-testing">2.1.1 Actual Testing<a class="headerlink" href="#211-actual-testing" title="Permanent link">¶</a></h2>
|
||||
<p>Suppose we have algorithms <code>A</code> and <code>B</code>, both capable of solving the same problem, and we need to compare their efficiencies. The most direct method is to use a computer to run these two algorithms and monitor and record their runtime and memory usage. This assessment method reflects the actual situation but has significant limitations.</p>
|
||||
<p>On one hand, <strong>it's difficult to eliminate interference from the testing environment</strong>. Hardware configurations can affect algorithm performance. For example, algorithm <code>A</code> might run faster than <code>B</code> on one computer, but the opposite result may occur on another computer with different configurations. This means we would need to test on a variety of machines to calculate average efficiency, which is impractical.</p>
|
||||
<p>On the other hand, <strong>conducting a full test is very resource-intensive</strong>. As the volume of input data changes, the efficiency of the algorithms may vary. For example, with smaller data volumes, algorithm <code>A</code> might run faster than <code>B</code>, but the opposite might be true with larger data volumes. Therefore, to draw convincing conclusions, we need to test a wide range of input data sizes, which requires significant computational resources.</p>
|
||||
<h2 id="212-theoretical-estimation">2.1.2 Theoretical Estimation<a class="headerlink" href="#212-theoretical-estimation" title="Permanent link">¶</a></h2>
|
||||
<p>Given the significant limitations of practical testing, we can consider assessing algorithm efficiency solely through calculations. This method of estimation is known as 'asymptotic complexity analysis,' often simply referred to as 'complexity analysis.</p>
|
||||
<p>Complexity analysis illustrates the relationship between the time (and space) resources required by an algorithm and the size of its input data. <strong>It describes the growing trend in the time and space required for the execution of an algorithm as the size of the input data increases</strong>. This definition might sound a bit complex, so let's break it down into three key points for easier understanding.</p>
|
||||
<p>Due to the significant limitations of actual testing, we can consider evaluating algorithm efficiency solely through calculations. This estimation method is known as "asymptotic complexity analysis," or simply "complexity analysis."</p>
|
||||
<p>Complexity analysis reflects the relationship between the time and space resources required for algorithm execution and the size of the input data. <strong>It describes the trend of growth in the time and space required by the algorithm as the size of the input data increases</strong>. This definition might sound complex, but we can break it down into three key points to understand it better.</p>
|
||||
<ul>
|
||||
<li>In complexity analysis, 'time and space' directly relate to 'time complexity' and 'space complexity,' respectively.</li>
|
||||
<li>The statement "as the size of the input data increases" highlights that complexity analysis examines the interplay between the size of the input data and the algorithm's efficiency.</li>
|
||||
<li>Lastly, the phrase "the growing trend in time and space required" emphasizes that the focus of complexity analysis is not on the specific values of running time or space occupied, but on the rate at which these requirements increase with larger input sizes.</li>
|
||||
<li>"Time and space resources" correspond to "time complexity" and "space complexity," respectively.</li>
|
||||
<li>"As the size of input data increases" means that complexity reflects the relationship between algorithm efficiency and the volume of input data.</li>
|
||||
<li>"The trend of growth in time and space" indicates that complexity analysis focuses not on the specific values of runtime or space occupied but on the "rate" at which time or space grows.</li>
|
||||
</ul>
|
||||
<p><strong>Complexity analysis overcomes the drawbacks of practical testing methods in two key ways:</strong>.</p>
|
||||
<p><strong>Complexity analysis overcomes the disadvantages of actual testing methods</strong>, reflected in the following aspects:</p>
|
||||
<ul>
|
||||
<li>It is independent of the testing environment, meaning the analysis results are applicable across all operating platforms.</li>
|
||||
<li>It effectively demonstrates the efficiency of algorithms with varying data volumes, particularly highlighting performance in large-scale data scenarios.</li>
|
||||
<li>It is independent of the testing environment and applicable to all operating platforms.</li>
|
||||
<li>It can reflect algorithm efficiency under different data volumes, especially in the performance of algorithms with large data volumes.</li>
|
||||
</ul>
|
||||
<div class="admonition tip">
|
||||
<p class="admonition-title">Tip</p>
|
||||
<p>If you're still finding the concept of complexity confusing, don't worry. We will cover it in more detail in the subsequent chapters.</p>
|
||||
<p>If you're still confused about the concept of complexity, don't worry. We will introduce it in detail in subsequent chapters.</p>
|
||||
</div>
|
||||
<p>Complexity analysis provides us with a 'ruler' for evaluating the efficiency of algorithms, enabling us to measure the time and space resources required to execute a given algorithm and to compare the efficiency of different algorithms.</p>
|
||||
<p>Complexity is a mathematical concept that might seem abstract and somewhat challenging for beginners. From this perspective, introducing complexity analysis at the very beginning may not be the most suitable approach. However, when discussing the characteristics of a particular data structure or algorithm, analyzing its operational speed and space usage is often inevitable.</p>
|
||||
<p>Therefore, it is recommended that before diving deeply into data structures and algorithms, <strong>one should first gain a basic understanding of complexity analysis. This foundational knowledge will facilitate the complexity analysis of simple algorithms.</strong></p>
|
||||
<p>Complexity analysis provides us with a "ruler" to measure the time and space resources needed to execute an algorithm and compare the efficiency between different algorithms.</p>
|
||||
<p>Complexity is a mathematical concept and may be abstract and challenging for beginners. From this perspective, complexity analysis might not be the best content to introduce first. However, when discussing the characteristics of a particular data structure or algorithm, it's hard to avoid analyzing its speed and space usage.</p>
|
||||
<p>In summary, it's recommended that you establish a preliminary understanding of complexity analysis before diving deep into data structures and algorithms, <strong>so that you can carry out simple complexity analyses of algorithms</strong>.</p>
|
||||
|
||||
<!-- Source file information -->
|
||||
|
||||
|
|
|
@ -739,9 +739,9 @@
|
|||
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#241-algorithmic-correlation-space" class="md-nav__link">
|
||||
<a href="#241-space-related-to-algorithms" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2.4.1 Algorithmic Correlation Space
|
||||
2.4.1 Space Related to Algorithms
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -778,7 +778,7 @@
|
|||
<li class="md-nav__item">
|
||||
<a href="#2-linear-order-on" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2. Linear Order \(O(N)\)
|
||||
2. Linear Order \(O(n)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -787,7 +787,7 @@
|
|||
<li class="md-nav__item">
|
||||
<a href="#3-quadratic-order-on2" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
3. Quadratic Order \(O(N^2)\)
|
||||
3. Quadratic Order \(O(n^2)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -796,7 +796,7 @@
|
|||
<li class="md-nav__item">
|
||||
<a href="#4-exponential-order-o2n" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
4. Exponential Order \(O(2^N)\)
|
||||
4. Exponential Order \(O(2^n)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -805,7 +805,7 @@
|
|||
<li class="md-nav__item">
|
||||
<a href="#5-logarithmic-order-olog-n" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
5. Logarithmic Order \(O(\Log N)\)
|
||||
5. Logarithmic Order \(O(\log n)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -817,9 +817,9 @@
|
|||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#244-weighing-time-and-space" class="md-nav__link">
|
||||
<a href="#244-balancing-time-and-space" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2.4.4 Weighing Time And Space
|
||||
2.4.4 Balancing Time and Space
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -889,9 +889,9 @@
|
|||
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#241-algorithmic-correlation-space" class="md-nav__link">
|
||||
<a href="#241-space-related-to-algorithms" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2.4.1 Algorithmic Correlation Space
|
||||
2.4.1 Space Related to Algorithms
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -928,7 +928,7 @@
|
|||
<li class="md-nav__item">
|
||||
<a href="#2-linear-order-on" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2. Linear Order \(O(N)\)
|
||||
2. Linear Order \(O(n)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -937,7 +937,7 @@
|
|||
<li class="md-nav__item">
|
||||
<a href="#3-quadratic-order-on2" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
3. Quadratic Order \(O(N^2)\)
|
||||
3. Quadratic Order \(O(n^2)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -946,7 +946,7 @@
|
|||
<li class="md-nav__item">
|
||||
<a href="#4-exponential-order-o2n" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
4. Exponential Order \(O(2^N)\)
|
||||
4. Exponential Order \(O(2^n)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -955,7 +955,7 @@
|
|||
<li class="md-nav__item">
|
||||
<a href="#5-logarithmic-order-olog-n" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
5. Logarithmic Order \(O(\Log N)\)
|
||||
5. Logarithmic Order \(O(\log n)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -967,9 +967,9 @@
|
|||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#244-weighing-time-and-space" class="md-nav__link">
|
||||
<a href="#244-balancing-time-and-space" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2.4.4 Weighing Time And Space
|
||||
2.4.4 Balancing Time and Space
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -1012,25 +1012,26 @@
|
|||
|
||||
<!-- Page content -->
|
||||
<h1 id="24-space-complexity">2.4 Space Complexity<a class="headerlink" href="#24-space-complexity" title="Permanent link">¶</a></h1>
|
||||
<p>The space complexity is used to measure the growth trend of memory consumption as the scale of data increases for an algorithm solution. This concept is analogous to time complexity by replacing "runtime" with "memory space".</p>
|
||||
<h2 id="241-algorithmic-correlation-space">2.4.1 Algorithmic Correlation Space<a class="headerlink" href="#241-algorithmic-correlation-space" title="Permanent link">¶</a></h2>
|
||||
<p>The memory space used by algorithms during its execution include the following types.</p>
|
||||
<p>"Space complexity" is used to measure the growth trend of the memory space occupied by an algorithm as the amount of data increases. This concept is very similar to time complexity, except that "running time" is replaced with "occupied memory space".</p>
|
||||
<h2 id="241-space-related-to-algorithms">2.4.1 Space Related to Algorithms<a class="headerlink" href="#241-space-related-to-algorithms" title="Permanent link">¶</a></h2>
|
||||
<p>The memory space used by an algorithm during its execution mainly includes the following types.</p>
|
||||
<ul>
|
||||
<li><strong>Input Space</strong>: Used to store the input data for the algorithm.</li>
|
||||
<li><strong>Temporary Space</strong>: Used to store variables, objects, function contexts, and other data of the algorithm during runtime.</li>
|
||||
<li><strong>Input Space</strong>: Used to store the input data of the algorithm.</li>
|
||||
<li><strong>Temporary Space</strong>: Used to store variables, objects, function contexts, and other data during the algorithm's execution.</li>
|
||||
<li><strong>Output Space</strong>: Used to store the output data of the algorithm.</li>
|
||||
</ul>
|
||||
<p>In general, the "Input Space" is excluded from the statistics of space complexity.</p>
|
||||
<p>The <strong>Temporary Space</strong> can be further divided into three parts.</p>
|
||||
<p>Generally, the scope of space complexity statistics includes both "Temporary Space" and "Output Space".</p>
|
||||
<p>Temporary space can be further divided into three parts.</p>
|
||||
<ul>
|
||||
<li><strong>Temporary Data</strong>: Used to store various constants, variables, objects, etc., during the the algorithm's execution.</li>
|
||||
<li><strong>Stack Frame Space</strong>: Used to hold the context data of the called function. The system creates a stack frame at the top of the stack each time a function is called, and the stack frame space is freed when the function returns.</li>
|
||||
<li><strong>Instruction Space</strong>: Used to hold compiled program instructions, usually ignored in practical statistics.</li>
|
||||
<li><strong>Temporary Data</strong>: Used to save various constants, variables, objects, etc., during the algorithm's execution.</li>
|
||||
<li><strong>Stack Frame Space</strong>: Used to save the context data of the called function. The system creates a stack frame at the top of the stack each time a function is called, and the stack frame space is released after the function returns.</li>
|
||||
<li><strong>Instruction Space</strong>: Used to store compiled program instructions, which are usually negligible in actual statistics.</li>
|
||||
</ul>
|
||||
<p>When analyzing the space complexity of a piece of program, <strong>three parts are usually taken into account: Temporary Data, Stack Frame Space and Output Data</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="Associated spaces used by the algorithm" class="animation-figure" src="../space_complexity.assets/space_types.png" /></a></p>
|
||||
<p align="center"> Figure 2-15 Associated spaces used by the algorithm </p>
|
||||
<p>When analyzing the space complexity of a program, <strong>we typically count the Temporary Data, Stack Frame Space, and Output Data</strong>, as shown in the Figure 2-15 .</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="Space Types Used in Algorithms" class="animation-figure" src="../space_complexity.assets/space_types.png" /></a></p>
|
||||
<p align="center"> Figure 2-15 Space Types Used in Algorithms </p>
|
||||
|
||||
<p>The relevant code is as follows:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="1:12"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><input id="__tabbed_1_3" name="__tabbed_1" type="radio" /><input id="__tabbed_1_4" name="__tabbed_1" type="radio" /><input id="__tabbed_1_5" name="__tabbed_1" type="radio" /><input id="__tabbed_1_6" name="__tabbed_1" type="radio" /><input id="__tabbed_1_7" name="__tabbed_1" type="radio" /><input id="__tabbed_1_8" name="__tabbed_1" type="radio" /><input id="__tabbed_1_9" name="__tabbed_1" type="radio" /><input id="__tabbed_1_10" name="__tabbed_1" type="radio" /><input id="__tabbed_1_11" name="__tabbed_1" type="radio" /><input id="__tabbed_1_12" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">Python</label><label for="__tabbed_1_2">C++</label><label for="__tabbed_1_3">Java</label><label for="__tabbed_1_4">C#</label><label for="__tabbed_1_5">Go</label><label for="__tabbed_1_6">Swift</label><label for="__tabbed_1_7">JS</label><label for="__tabbed_1_8">TS</label><label for="__tabbed_1_9">Dart</label><label for="__tabbed_1_10">Rust</label><label for="__tabbed_1_11">C</label><label for="__tabbed_1_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -1304,12 +1305,12 @@
|
|||
</div>
|
||||
</div>
|
||||
<h2 id="242-calculation-method">2.4.2 Calculation Method<a class="headerlink" href="#242-calculation-method" title="Permanent link">¶</a></h2>
|
||||
<p>The calculation method for space complexity is pretty similar to time complexity, with the only difference being that the focus shifts from "operation count" to "space usage size".</p>
|
||||
<p>On top of that, unlike time complexity, <strong>we usually only focus on the worst-case space complexity</strong>. This is because memory space is a hard requirement, and we have to make sure that there is enough memory space reserved for all possibilities incurred by input data.</p>
|
||||
<p>Looking at the following code, the "worst" in worst-case space complexity has two layers of meaning.</p>
|
||||
<p>The method for calculating space complexity is roughly similar to that of time complexity, with the only change being the shift of the statistical object from "number of operations" to "size of used space".</p>
|
||||
<p>However, unlike time complexity, <strong>we usually only focus on the worst-case space complexity</strong>. This is because memory space is a hard requirement, and we must ensure that there is enough memory space reserved under all input data.</p>
|
||||
<p>Consider the following code, the term "worst-case" in worst-case space complexity has two meanings.</p>
|
||||
<ol>
|
||||
<li><strong>Based on the worst-case input data</strong>: when <span class="arithmatex">\(n < 10\)</span>, the space complexity is <span class="arithmatex">\(O(1)\)</span>; however, when <span class="arithmatex">\(n > 10\)</span>, the initialized array <code>nums</code> occupies <span class="arithmatex">\(O(n)\)</span> space; thus the worst-case space complexity is <span class="arithmatex">\(O(n)\)</span>.</li>
|
||||
<li><strong>Based on the peak memory during algorithm execution</strong>: for example, the program occupies <span class="arithmatex">\(O(1)\)</span> space until the last line is executed; when the array <code>nums</code> is initialized, the program occupies <span class="arithmatex">\(O(n)\)</span> space; thus the worst-case space complexity is <span class="arithmatex">\(O(n)\)</span>.</li>
|
||||
<li><strong>Based on the worst input data</strong>: When <span class="arithmatex">\(n < 10\)</span>, the space complexity is <span class="arithmatex">\(O(1)\)</span>; but when <span class="arithmatex">\(n > 10\)</span>, the initialized array <code>nums</code> occupies <span class="arithmatex">\(O(n)\)</span> space, thus the worst-case space complexity is <span class="arithmatex">\(O(n)\)</span>.</li>
|
||||
<li><strong>Based on the peak memory used during the algorithm's execution</strong>: For example, before executing the last line, the program occupies <span class="arithmatex">\(O(1)\)</span> space; when initializing the array <code>nums</code>, the program occupies <span class="arithmatex">\(O(n)\)</span> space, hence the worst-case space complexity is <span class="arithmatex">\(O(n)\)</span>.</li>
|
||||
</ol>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="2:12"><input checked="checked" id="__tabbed_2_1" name="__tabbed_2" type="radio" /><input id="__tabbed_2_2" name="__tabbed_2" type="radio" /><input id="__tabbed_2_3" name="__tabbed_2" type="radio" /><input id="__tabbed_2_4" name="__tabbed_2" type="radio" /><input id="__tabbed_2_5" name="__tabbed_2" type="radio" /><input id="__tabbed_2_6" name="__tabbed_2" type="radio" /><input id="__tabbed_2_7" name="__tabbed_2" type="radio" /><input id="__tabbed_2_8" name="__tabbed_2" type="radio" /><input id="__tabbed_2_9" name="__tabbed_2" type="radio" /><input id="__tabbed_2_10" name="__tabbed_2" type="radio" /><input id="__tabbed_2_11" name="__tabbed_2" type="radio" /><input id="__tabbed_2_12" name="__tabbed_2" type="radio" /><div class="tabbed-labels"><label for="__tabbed_2_1">Python</label><label for="__tabbed_2_2">C++</label><label for="__tabbed_2_3">Java</label><label for="__tabbed_2_4">C#</label><label for="__tabbed_2_5">Go</label><label for="__tabbed_2_6">Swift</label><label for="__tabbed_2_7">JS</label><label for="__tabbed_2_8">TS</label><label for="__tabbed_2_9">Dart</label><label for="__tabbed_2_10">Rust</label><label for="__tabbed_2_11">C</label><label for="__tabbed_2_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
|
@ -1426,11 +1427,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p><strong>In recursion functions, it is important to take into count the measurement of stack frame space</strong>. For example in the following code:</p>
|
||||
<ul>
|
||||
<li>The function <code>loop()</code> calls <span class="arithmatex">\(n\)</span> times <code>function()</code> in a loop, and each round of <code>function()</code> returns and frees stack frame space, so the space complexity is still <span class="arithmatex">\(O(1)\)</span>.</li>
|
||||
<li>The recursion function <code>recur()</code> will have <span class="arithmatex">\(n\)</span> unreturned <code>recur()</code> during runtime, thus occupying <span class="arithmatex">\(O(n)\)</span> of stack frame space.</li>
|
||||
</ul>
|
||||
<p><strong>In recursive functions, stack frame space must be taken into count</strong>. Consider the following code:</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>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -1646,20 +1643,25 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>The time complexity of both <code>loop()</code> and <code>recur()</code> functions is <span class="arithmatex">\(O(n)\)</span>, but their space complexities differ.</p>
|
||||
<ul>
|
||||
<li>The <code>loop()</code> function calls <code>function()</code> <span class="arithmatex">\(n\)</span> times in a loop, where each iteration's <code>function()</code> returns and releases its stack frame space, so the space complexity remains <span class="arithmatex">\(O(1)\)</span>.</li>
|
||||
<li>The recursive function <code>recur()</code> will have <span class="arithmatex">\(n\)</span> instances of unreturned <code>recur()</code> existing simultaneously during its execution, thus occupying <span class="arithmatex">\(O(n)\)</span> stack frame space.</li>
|
||||
</ul>
|
||||
<h2 id="243-common-types">2.4.3 Common Types<a class="headerlink" href="#243-common-types" title="Permanent link">¶</a></h2>
|
||||
<p>Assuming the input data size is <span class="arithmatex">\(n\)</span>, the figure illustrates common types of space complexity (ordered from low to high).</p>
|
||||
<p>Let the size of the input data be <span class="arithmatex">\(n\)</span>, the following chart displays common types of space complexities (arranged from low to high).</p>
|
||||
<div class="arithmatex">\[
|
||||
\begin{aligned}
|
||||
O(1) < O(\log n) < O(n) < O(n^2) < O(2^n) \newline
|
||||
\text{constant order} < \text{logarithmic order} < \text{linear order} < \text{square order} < \text{exponential order}
|
||||
\text{Constant Order} < \text{Logarithmic Order} < \text{Linear Order} < \text{Quadratic Order} < \text{Exponential Order}
|
||||
\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="Common space complexity types" class="animation-figure" src="../space_complexity.assets/space_complexity_common_types.png" /></a></p>
|
||||
<p align="center"> Figure 2-16 Common space complexity types </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="Common Types of Space Complexity" class="animation-figure" src="../space_complexity.assets/space_complexity_common_types.png" /></a></p>
|
||||
<p align="center"> Figure 2-16 Common Types of Space Complexity </p>
|
||||
|
||||
<h3 id="1-constant-order-o1">1. Constant Order <span class="arithmatex">\(O(1)\)</span><a class="headerlink" href="#1-constant-order-o1" title="Permanent link">¶</a></h3>
|
||||
<p>Constant order is common for constants, variables, and objects whose quantity is unrelated to the size of the input data <span class="arithmatex">\(n\)</span>.</p>
|
||||
<p>It is important to note that memory occupied by initializing a variable or calling a function in a loop is released once the next iteration begins. Therefore, there is no accumulation of occupied space and the space complexity remains <span class="arithmatex">\(O(1)\)</span> :</p>
|
||||
<p>Constant order is common in constants, variables, objects that are independent of the size of input data <span class="arithmatex">\(n\)</span>.</p>
|
||||
<p>Note that memory occupied by initializing variables or calling functions in a loop, which is released upon entering the next cycle, does not accumulate over space, thus the space complexity remains <span class="arithmatex">\(O(1)\)</span>:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="4:12"><input checked="checked" id="__tabbed_4_1" name="__tabbed_4" type="radio" /><input id="__tabbed_4_2" name="__tabbed_4" type="radio" /><input id="__tabbed_4_3" name="__tabbed_4" type="radio" /><input id="__tabbed_4_4" name="__tabbed_4" type="radio" /><input id="__tabbed_4_5" name="__tabbed_4" type="radio" /><input id="__tabbed_4_6" name="__tabbed_4" type="radio" /><input id="__tabbed_4_7" name="__tabbed_4" type="radio" /><input id="__tabbed_4_8" name="__tabbed_4" type="radio" /><input id="__tabbed_4_9" name="__tabbed_4" type="radio" /><input id="__tabbed_4_10" name="__tabbed_4" type="radio" /><input id="__tabbed_4_11" name="__tabbed_4" type="radio" /><input id="__tabbed_4_12" name="__tabbed_4" type="radio" /><div class="tabbed-labels"><label for="__tabbed_4_1">Python</label><label for="__tabbed_4_2">C++</label><label for="__tabbed_4_3">Java</label><label for="__tabbed_4_4">C#</label><label for="__tabbed_4_5">Go</label><label for="__tabbed_4_6">Swift</label><label for="__tabbed_4_7">JS</label><label for="__tabbed_4_8">TS</label><label for="__tabbed_4_9">Dart</label><label for="__tabbed_4_10">Rust</label><label for="__tabbed_4_11">C</label><label for="__tabbed_4_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -1971,8 +1973,8 @@ O(1) < O(\log n) < O(n) < O(n^2) < O(2^n) \newline
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h3 id="2-linear-order-on">2. Linear Order <span class="arithmatex">\(O(N)\)</span><a class="headerlink" href="#2-linear-order-on" title="Permanent link">¶</a></h3>
|
||||
<p>Linear order is commonly found in arrays, linked lists, stacks, queues, and similar structures where the number of elements is proportional to <span class="arithmatex">\(n\)</span>:</p>
|
||||
<h3 id="2-linear-order-on">2. Linear Order <span class="arithmatex">\(O(n)\)</span><a class="headerlink" href="#2-linear-order-on" title="Permanent link">¶</a></h3>
|
||||
<p>Linear order is common in arrays, linked lists, stacks, queues, etc., where the number of elements is proportional to <span class="arithmatex">\(n\)</span>:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="5:12"><input checked="checked" id="__tabbed_5_1" name="__tabbed_5" type="radio" /><input id="__tabbed_5_2" name="__tabbed_5" type="radio" /><input id="__tabbed_5_3" name="__tabbed_5" type="radio" /><input id="__tabbed_5_4" name="__tabbed_5" type="radio" /><input id="__tabbed_5_5" name="__tabbed_5" type="radio" /><input id="__tabbed_5_6" name="__tabbed_5" type="radio" /><input id="__tabbed_5_7" name="__tabbed_5" type="radio" /><input id="__tabbed_5_8" name="__tabbed_5" type="radio" /><input id="__tabbed_5_9" name="__tabbed_5" type="radio" /><input id="__tabbed_5_10" name="__tabbed_5" type="radio" /><input id="__tabbed_5_11" name="__tabbed_5" type="radio" /><input id="__tabbed_5_12" name="__tabbed_5" type="radio" /><div class="tabbed-labels"><label for="__tabbed_5_1">Python</label><label for="__tabbed_5_2">C++</label><label for="__tabbed_5_3">Java</label><label for="__tabbed_5_4">C#</label><label for="__tabbed_5_5">Go</label><label for="__tabbed_5_6">Swift</label><label for="__tabbed_5_7">JS</label><label for="__tabbed_5_8">TS</label><label for="__tabbed_5_9">Dart</label><label for="__tabbed_5_10">Rust</label><label for="__tabbed_5_11">C</label><label for="__tabbed_5_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -2213,7 +2215,7 @@ O(1) < O(\log n) < O(n) < O(n^2) < O(2^n) \newline
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>As shown in the Figure 2-17 , the depth of recursion for this function is <span class="arithmatex">\(n\)</span>, which means that there are <span class="arithmatex">\(n\)</span> unreturned <code>linear_recur()</code> functions at the same time, using <span class="arithmatex">\(O(n)\)</span> size stack frame space:</p>
|
||||
<p>As shown below, this function's recursive depth is <span class="arithmatex">\(n\)</span>, meaning there are <span class="arithmatex">\(n\)</span> instances of unreturned <code>linear_recur()</code> function, using <span class="arithmatex">\(O(n)\)</span> size of stack frame space:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="6:12"><input checked="checked" id="__tabbed_6_1" name="__tabbed_6" type="radio" /><input id="__tabbed_6_2" name="__tabbed_6" type="radio" /><input id="__tabbed_6_3" name="__tabbed_6" type="radio" /><input id="__tabbed_6_4" name="__tabbed_6" type="radio" /><input id="__tabbed_6_5" name="__tabbed_6" type="radio" /><input id="__tabbed_6_6" name="__tabbed_6" type="radio" /><input id="__tabbed_6_7" name="__tabbed_6" type="radio" /><input id="__tabbed_6_8" name="__tabbed_6" type="radio" /><input id="__tabbed_6_9" name="__tabbed_6" type="radio" /><input id="__tabbed_6_10" name="__tabbed_6" type="radio" /><input id="__tabbed_6_11" name="__tabbed_6" type="radio" /><input id="__tabbed_6_12" name="__tabbed_6" type="radio" /><div class="tabbed-labels"><label for="__tabbed_6_1">Python</label><label for="__tabbed_6_2">C++</label><label for="__tabbed_6_3">Java</label><label for="__tabbed_6_4">C#</label><label for="__tabbed_6_5">Go</label><label for="__tabbed_6_6">Swift</label><label for="__tabbed_6_7">JS</label><label for="__tabbed_6_8">TS</label><label for="__tabbed_6_9">Dart</label><label for="__tabbed_6_10">Rust</label><label for="__tabbed_6_11">C</label><label for="__tabbed_6_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -2333,11 +2335,11 @@ 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="Linear order space complexity generated by recursion function" class="animation-figure" src="../space_complexity.assets/space_complexity_recursive_linear.png" /></a></p>
|
||||
<p align="center"> Figure 2-17 Linear order space complexity generated by recursion function </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="Recursive Function Generating Linear Order Space Complexity" class="animation-figure" src="../space_complexity.assets/space_complexity_recursive_linear.png" /></a></p>
|
||||
<p align="center"> Figure 2-17 Recursive Function Generating Linear Order Space Complexity </p>
|
||||
|
||||
<h3 id="3-quadratic-order-on2">3. Quadratic Order <span class="arithmatex">\(O(N^2)\)</span><a class="headerlink" href="#3-quadratic-order-on2" title="Permanent link">¶</a></h3>
|
||||
<p>Quadratic order is common in matrices and graphs, where the number of elements is in a square relationship with <span class="arithmatex">\(n\)</span>:</p>
|
||||
<h3 id="3-quadratic-order-on2">3. Quadratic Order <span class="arithmatex">\(O(n^2)\)</span><a class="headerlink" href="#3-quadratic-order-on2" title="Permanent link">¶</a></h3>
|
||||
<p>Quadratic order is common in matrices and graphs, where the number of elements is quadratic to <span class="arithmatex">\(n\)</span>:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="7:12"><input checked="checked" id="__tabbed_7_1" name="__tabbed_7" type="radio" /><input id="__tabbed_7_2" name="__tabbed_7" type="radio" /><input id="__tabbed_7_3" name="__tabbed_7" type="radio" /><input id="__tabbed_7_4" name="__tabbed_7" type="radio" /><input id="__tabbed_7_5" name="__tabbed_7" type="radio" /><input id="__tabbed_7_6" name="__tabbed_7" type="radio" /><input id="__tabbed_7_7" name="__tabbed_7" type="radio" /><input id="__tabbed_7_8" name="__tabbed_7" type="radio" /><input id="__tabbed_7_9" name="__tabbed_7" type="radio" /><input id="__tabbed_7_10" name="__tabbed_7" type="radio" /><input id="__tabbed_7_11" name="__tabbed_7" type="radio" /><input id="__tabbed_7_12" name="__tabbed_7" type="radio" /><div class="tabbed-labels"><label for="__tabbed_7_1">Python</label><label for="__tabbed_7_2">C++</label><label for="__tabbed_7_3">Java</label><label for="__tabbed_7_4">C#</label><label for="__tabbed_7_5">Go</label><label for="__tabbed_7_6">Swift</label><label for="__tabbed_7_7">JS</label><label for="__tabbed_7_8">TS</label><label for="__tabbed_7_9">Dart</label><label for="__tabbed_7_10">Rust</label><label for="__tabbed_7_11">C</label><label for="__tabbed_7_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -2530,7 +2532,7 @@ O(1) < O(\log n) < O(n) < O(n^2) < O(2^n) \newline
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>As shown in the Figure 2-18 , the recursion depth of this function is <span class="arithmatex">\(n\)</span>, and an array is initialized in each recursion function with lengths <span class="arithmatex">\(n\)</span>, <span class="arithmatex">\(n-1\)</span>, <span class="arithmatex">\(\dots\)</span>, <span class="arithmatex">\(2\)</span>, <span class="arithmatex">\(1\)</span>, and an average length of <span class="arithmatex">\(n / 2\)</span>, thus occupying <span class="arithmatex">\(O(n^2)\)</span> space overall:</p>
|
||||
<p>As shown below, the recursive depth of this function is <span class="arithmatex">\(n\)</span>, and in each recursive call, an array is initialized with lengths <span class="arithmatex">\(n\)</span>, <span class="arithmatex">\(n-1\)</span>, <span class="arithmatex">\(\dots\)</span>, <span class="arithmatex">\(2\)</span>, <span class="arithmatex">\(1\)</span>, averaging <span class="arithmatex">\(n/2\)</span>, thus overall occupying <span class="arithmatex">\(O(n^2)\)</span> space:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="8:12"><input checked="checked" id="__tabbed_8_1" name="__tabbed_8" type="radio" /><input id="__tabbed_8_2" name="__tabbed_8" type="radio" /><input id="__tabbed_8_3" name="__tabbed_8" type="radio" /><input id="__tabbed_8_4" name="__tabbed_8" type="radio" /><input id="__tabbed_8_5" name="__tabbed_8" type="radio" /><input id="__tabbed_8_6" name="__tabbed_8" type="radio" /><input id="__tabbed_8_7" name="__tabbed_8" type="radio" /><input id="__tabbed_8_8" name="__tabbed_8" type="radio" /><input id="__tabbed_8_9" name="__tabbed_8" type="radio" /><input id="__tabbed_8_10" name="__tabbed_8" type="radio" /><input id="__tabbed_8_11" name="__tabbed_8" type="radio" /><input id="__tabbed_8_12" name="__tabbed_8" type="radio" /><div class="tabbed-labels"><label for="__tabbed_8_1">Python</label><label for="__tabbed_8_2">C++</label><label for="__tabbed_8_3">Java</label><label for="__tabbed_8_4">C#</label><label for="__tabbed_8_5">Go</label><label for="__tabbed_8_6">Swift</label><label for="__tabbed_8_7">JS</label><label for="__tabbed_8_8">TS</label><label for="__tabbed_8_9">Dart</label><label for="__tabbed_8_10">Rust</label><label for="__tabbed_8_11">C</label><label for="__tabbed_8_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -2668,11 +2670,11 @@ 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="Square-order space complexity generated by the recursion function" class="animation-figure" src="../space_complexity.assets/space_complexity_recursive_quadratic.png" /></a></p>
|
||||
<p align="center"> Figure 2-18 Square-order space complexity generated by the recursion function </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="Recursive Function Generating Quadratic Order Space Complexity" class="animation-figure" src="../space_complexity.assets/space_complexity_recursive_quadratic.png" /></a></p>
|
||||
<p align="center"> Figure 2-18 Recursive Function Generating Quadratic Order Space Complexity </p>
|
||||
|
||||
<h3 id="4-exponential-order-o2n">4. Exponential Order <span class="arithmatex">\(O(2^N)\)</span><a class="headerlink" href="#4-exponential-order-o2n" title="Permanent link">¶</a></h3>
|
||||
<p>Exponential order is common in binary trees. Looking at the Figure 2-19 , a "full binary tree" of degree <span class="arithmatex">\(n\)</span> has <span class="arithmatex">\(2^n - 1\)</span> nodes, occupying <span class="arithmatex">\(O(2^n)\)</span> space:</p>
|
||||
<h3 id="4-exponential-order-o2n">4. Exponential Order <span class="arithmatex">\(O(2^n)\)</span><a class="headerlink" href="#4-exponential-order-o2n" title="Permanent link">¶</a></h3>
|
||||
<p>Exponential order is common in binary trees. Observe the below image, a "full binary tree" with <span class="arithmatex">\(n\)</span> levels has <span class="arithmatex">\(2^n - 1\)</span> nodes, occupying <span class="arithmatex">\(O(2^n)\)</span> space:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="9:12"><input checked="checked" id="__tabbed_9_1" name="__tabbed_9" type="radio" /><input id="__tabbed_9_2" name="__tabbed_9" type="radio" /><input id="__tabbed_9_3" name="__tabbed_9" type="radio" /><input id="__tabbed_9_4" name="__tabbed_9" type="radio" /><input id="__tabbed_9_5" name="__tabbed_9" type="radio" /><input id="__tabbed_9_6" name="__tabbed_9" type="radio" /><input id="__tabbed_9_7" name="__tabbed_9" type="radio" /><input id="__tabbed_9_8" name="__tabbed_9" type="radio" /><input id="__tabbed_9_9" name="__tabbed_9" type="radio" /><input id="__tabbed_9_10" name="__tabbed_9" type="radio" /><input id="__tabbed_9_11" name="__tabbed_9" type="radio" /><input id="__tabbed_9_12" name="__tabbed_9" type="radio" /><div class="tabbed-labels"><label for="__tabbed_9_1">Python</label><label for="__tabbed_9_2">C++</label><label for="__tabbed_9_3">Java</label><label for="__tabbed_9_4">C#</label><label for="__tabbed_9_5">Go</label><label for="__tabbed_9_6">Swift</label><label for="__tabbed_9_7">JS</label><label for="__tabbed_9_8">TS</label><label for="__tabbed_9_9">Dart</label><label for="__tabbed_9_10">Rust</label><label for="__tabbed_9_11">C</label><label for="__tabbed_9_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -2818,16 +2820,16 @@ 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="Exponential order space complexity generated by a full binary tree" class="animation-figure" src="../space_complexity.assets/space_complexity_exponential.png" /></a></p>
|
||||
<p align="center"> Figure 2-19 Exponential order space complexity generated by a full binary tree </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="Full Binary Tree Generating Exponential Order Space Complexity" class="animation-figure" src="../space_complexity.assets/space_complexity_exponential.png" /></a></p>
|
||||
<p align="center"> Figure 2-19 Full Binary Tree Generating Exponential Order Space Complexity </p>
|
||||
|
||||
<h3 id="5-logarithmic-order-olog-n">5. Logarithmic Order <span class="arithmatex">\(O(\Log N)\)</span><a class="headerlink" href="#5-logarithmic-order-olog-n" title="Permanent link">¶</a></h3>
|
||||
<p>Logarithmic order is commonly used in divide and conquer algorithms. For example, in a merge sort, given an array of length <span class="arithmatex">\(n\)</span> as the input, each round of recursion divides the array in half from its midpoint to form a recursion tree of height <span class="arithmatex">\(\log n\)</span>, using <span class="arithmatex">\(O(\log n)\)</span> stack frame space.</p>
|
||||
<p>Another example is to convert a number into a string. Given a positive integer <span class="arithmatex">\(n\)</span> with a digit count of <span class="arithmatex">\(\log_{10} n + 1\)</span>, the corresponding string length is <span class="arithmatex">\(\log_{10} n + 1\)</span>. Therefore, the space complexity is <span class="arithmatex">\(O(\log_{10} n + 1) = O(\log n)\)</span>.</p>
|
||||
<h2 id="244-weighing-time-and-space">2.4.4 Weighing Time And Space<a class="headerlink" href="#244-weighing-time-and-space" title="Permanent link">¶</a></h2>
|
||||
<p>Ideally, we would like to optimize both the time complexity and the space complexity of an algorithm. However, in reality, simultaneously optimizing time and space complexity is often challenging.</p>
|
||||
<p><strong>Reducing time complexity usually comes at the expense of increasing space complexity, and vice versa</strong>. The approach of sacrificing memory space to improve algorithm speed is known as "trading space for time", while the opposite is called "trading time for space".</p>
|
||||
<p>The choice between these approaches depends on which aspect we prioritize. In most cases, time is more valuable than space, so "trading space for time" is usually the more common strategy. Of course, in situations with large data volumes, controlling space complexity is also crucial.</p>
|
||||
<h3 id="5-logarithmic-order-olog-n">5. Logarithmic Order <span class="arithmatex">\(O(\log n)\)</span><a class="headerlink" href="#5-logarithmic-order-olog-n" title="Permanent link">¶</a></h3>
|
||||
<p>Logarithmic order is common in divide-and-conquer algorithms. For example, in merge sort, an array of length <span class="arithmatex">\(n\)</span> is recursively divided in half each round, forming a recursion tree of height <span class="arithmatex">\(\log n\)</span>, using <span class="arithmatex">\(O(\log n)\)</span> stack frame space.</p>
|
||||
<p>Another example is converting a number to a string. Given a positive integer <span class="arithmatex">\(n\)</span>, its number of digits is <span class="arithmatex">\(\log_{10} n + 1\)</span>, corresponding to the length of the string, thus the space complexity is <span class="arithmatex">\(O(\log_{10} n + 1) = O(\log n)\)</span>.</p>
|
||||
<h2 id="244-balancing-time-and-space">2.4.4 Balancing Time and Space<a class="headerlink" href="#244-balancing-time-and-space" title="Permanent link">¶</a></h2>
|
||||
<p>Ideally, we aim for both time complexity and space complexity to be optimal. However, in practice, optimizing both simultaneously is often difficult.</p>
|
||||
<p><strong>Lowering time complexity usually comes at the cost of increased space complexity, and vice versa</strong>. The approach of sacrificing memory space to improve algorithm speed is known as "space-time tradeoff"; the reverse is known as "time-space tradeoff".</p>
|
||||
<p>The choice depends on which aspect we value more. In most cases, time is more precious than space, so "space-time tradeoff" is often the more common strategy. Of course, controlling space complexity is also very important when dealing with large volumes of data.</p>
|
||||
|
||||
<!-- Source file information -->
|
||||
|
||||
|
|
|
@ -758,9 +758,9 @@
|
|||
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#1-highlights" class="md-nav__link">
|
||||
<a href="#1-key-review" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
1. Highlights
|
||||
1. Key Review
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -818,9 +818,9 @@
|
|||
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#1-highlights" class="md-nav__link">
|
||||
<a href="#1-key-review" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
1. Highlights
|
||||
1. Key Review
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -872,49 +872,49 @@
|
|||
|
||||
<!-- Page content -->
|
||||
<h1 id="25-summary">2.5 Summary<a class="headerlink" href="#25-summary" title="Permanent link">¶</a></h1>
|
||||
<h3 id="1-highlights">1. Highlights<a class="headerlink" href="#1-highlights" title="Permanent link">¶</a></h3>
|
||||
<p><strong>Evaluation of Algorithm Efficiency</strong></p>
|
||||
<h3 id="1-key-review">1. Key Review<a class="headerlink" href="#1-key-review" title="Permanent link">¶</a></h3>
|
||||
<p><strong>Algorithm Efficiency Assessment</strong></p>
|
||||
<ul>
|
||||
<li>Time and space efficiency are the two leading evaluation indicators to measure an algorithm.</li>
|
||||
<li>We can evaluate the efficiency of an algorithm through real-world testing. Still, it isn't easy to eliminate the side effects from the testing environment, and it consumes a lot of computational resources.</li>
|
||||
<li>Complexity analysis overcomes the drawbacks of real-world testing. The analysis results can apply to all operating platforms and reveal the algorithm's efficiency under variant data scales.</li>
|
||||
<li>Time efficiency and space efficiency are the two main criteria for assessing the merits of an algorithm.</li>
|
||||
<li>We can assess algorithm efficiency through actual testing, but it's challenging to eliminate the influence of the test environment, and it consumes substantial computational resources.</li>
|
||||
<li>Complexity analysis can overcome the disadvantages of actual testing. Its results are applicable across all operating platforms and can reveal the efficiency of algorithms at different data scales.</li>
|
||||
</ul>
|
||||
<p><strong>Time Complexity</strong></p>
|
||||
<ul>
|
||||
<li>Time complexity is used to measure the trend of algorithm running time as the data size grows., which can effectively evaluate the algorithm's efficiency. However, it may fail in some cases, such as when the input volume is small or the time complexities are similar, making it difficult to precisely compare the efficiency of algorithms.</li>
|
||||
<li>The worst time complexity is denoted by big <span class="arithmatex">\(O\)</span> notation, which corresponds to the asymptotic upper bound of the function, reflecting the growth rate in the number of operations <span class="arithmatex">\(T(n)\)</span> as <span class="arithmatex">\(n\)</span> tends to positive infinity.</li>
|
||||
<li>The estimation of time complexity involves two steps: first, counting the number of operations, and then determining the asymptotic upper bound.</li>
|
||||
<li>Common time complexities, from lowest to highest, are <span class="arithmatex">\(O(1)\)</span>, <span class="arithmatex">\(O(\log n)\)</span>, <span class="arithmatex">\(O(n)\)</span>, <span class="arithmatex">\(O(n \log n)\)</span>, <span class="arithmatex">\(O(n^2)\)</span>, <span class="arithmatex">\(O(2^n)\)</span>, and <span class="arithmatex">\(O(n!)\)</span>.</li>
|
||||
<li>The time complexity of certain algorithms is not fixed and depends on the distribution of the input data. The time complexity can be categorized into worst-case, best-case, and average. The best-case time complexity is rarely used because the input data must meet strict conditions to achieve the best-case.</li>
|
||||
<li>The average time complexity reflects the efficiency of an algorithm with random data inputs, which is closest to the performance of algorithms in real-world scenarios. Calculating the average time complexity requires statistical analysis of input data and a synthesized mathematical expectation.</li>
|
||||
<li>Time complexity measures the trend of an algorithm's running time with the increase in data volume, effectively assessing algorithm efficiency. However, it can fail in certain cases, such as with small input data volumes or when time complexities are the same, making it challenging to precisely compare the efficiency of algorithms.</li>
|
||||
<li>Worst-case time complexity is denoted using big O notation, representing the asymptotic upper bound, reflecting the growth level of the number of operations <span class="arithmatex">\(T(n)\)</span> as <span class="arithmatex">\(n\)</span> approaches infinity.</li>
|
||||
<li>Calculating time complexity involves two steps: first counting the number of operations, then determining the asymptotic upper bound.</li>
|
||||
<li>Common time complexities, arranged from low to high, include <span class="arithmatex">\(O(1)\)</span>, <span class="arithmatex">\(O(\log n)\)</span>, <span class="arithmatex">\(O(n)\)</span>, <span class="arithmatex">\(O(n \log n)\)</span>, <span class="arithmatex">\(O(n^2)\)</span>, <span class="arithmatex">\(O(2^n)\)</span>, and <span class="arithmatex">\(O(n!)\)</span>, among others.</li>
|
||||
<li>The time complexity of some algorithms is not fixed and depends on the distribution of input data. Time complexities are divided into worst, best, and average cases. The best case is rarely used because input data generally needs to meet strict conditions to achieve the best case.</li>
|
||||
<li>Average time complexity reflects the efficiency of an algorithm under random data inputs, closely resembling the algorithm's performance in actual applications. Calculating average time complexity requires accounting for the distribution of input data and the subsequent mathematical expectation.</li>
|
||||
</ul>
|
||||
<p><strong>Space Complexity</strong></p>
|
||||
<ul>
|
||||
<li>Space complexity serves a similar purpose to time complexity and is used to measure the trend of space occupied by an algorithm as the data volume increases.</li>
|
||||
<li>The memory space associated with the operation of an algorithm can be categorized into input space, temporary space, and output space. Normally, the input space is not considered when determining space complexity. The temporary space can be classified into instruction space, data space, and stack frame space, and the stack frame space usually only affects the space complexity for recursion functions.</li>
|
||||
<li>We mainly focus on the worst-case space complexity, which refers to the measurement of an algorithm's space usage when given the worst-case input data and during the worst-case execution scenario.</li>
|
||||
<li>Common space complexities are <span class="arithmatex">\(O(1)\)</span>, <span class="arithmatex">\(O(\log n)\)</span>, <span class="arithmatex">\(O(n)\)</span>, <span class="arithmatex">\(O(n^2)\)</span> and <span class="arithmatex">\(O(2^n)\)</span> from lowest to highest.</li>
|
||||
<li>Space complexity, similar to time complexity, measures the trend of memory space occupied by an algorithm with the increase in data volume.</li>
|
||||
<li>The relevant memory space used during the algorithm's execution can be divided into input space, temporary space, and output space. Generally, input space is not included in space complexity calculations. Temporary space can be divided into temporary data, stack frame space, and instruction space, where stack frame space usually affects space complexity only in recursive functions.</li>
|
||||
<li>We usually focus only on the worst-case space complexity, which means calculating the space complexity of the algorithm under the worst input data and at the worst moment of operation.</li>
|
||||
<li>Common space complexities, arranged from low to high, include <span class="arithmatex">\(O(1)\)</span>, <span class="arithmatex">\(O(\log n)\)</span>, <span class="arithmatex">\(O(n)\)</span>, <span class="arithmatex">\(O(n^2)\)</span>, and <span class="arithmatex">\(O(2^n)\)</span>, among others.</li>
|
||||
</ul>
|
||||
<h3 id="2-q-a">2. Q & A<a class="headerlink" href="#2-q-a" title="Permanent link">¶</a></h3>
|
||||
<div class="admonition question">
|
||||
<p class="admonition-title">Is the space complexity of tail recursion <span class="arithmatex">\(O(1)\)</span>?</p>
|
||||
<p>Theoretically, the space complexity of a tail recursion function can be optimized to <span class="arithmatex">\(O(1)\)</span>. However, most programming languages (e.g., Java, Python, C++, Go, C#, etc.) do not support auto-optimization for tail recursion, so the space complexity is usually considered as <span class="arithmatex">\(O(n)\)</span>.</p>
|
||||
<p>Theoretically, the space complexity of a tail-recursive function can be optimized to <span class="arithmatex">\(O(1)\)</span>. However, most programming languages (such as Java, Python, C++, Go, C#) do not support automatic optimization of tail recursion, so it's generally considered to have a space complexity of <span class="arithmatex">\(O(n)\)</span>.</p>
|
||||
</div>
|
||||
<div class="admonition question">
|
||||
<p class="admonition-title">What is the difference between the terms function and method?</p>
|
||||
<p>A <em>function</em> can be executed independently, and all arguments are passed explicitly. A <em>method</em> is associated with an object and is implicitly passed to the object that calls it, allowing it to operate on the data contained within an instance of a class.</p>
|
||||
<p>Let's illustrate with a few common programming languages.</p>
|
||||
<p class="admonition-title">What is the difference between the terms 'function' and 'method'?</p>
|
||||
<p>A "function" can be executed independently, with all parameters passed explicitly. A "method" is associated with an object and is implicitly passed to the object calling it, able to operate on the data contained within an instance of a class.</p>
|
||||
<p>Here are some examples from common programming languages:</p>
|
||||
<ul>
|
||||
<li>C is a procedural programming language without object-oriented concepts, so it has only functions. However, we can simulate object-oriented programming by creating structures (struct), and the functions associated with structures are equivalent to methods in other languages.</li>
|
||||
<li>Java and C# are object-oriented programming languages, and blocks of code (methods) are typically part of a class. Static methods behave like a function because it is bound to the class and cannot access specific instance variables.</li>
|
||||
<li>Both C++ and Python support both procedural programming (functions) and object-oriented programming (methods).</li>
|
||||
<li>C is a procedural programming language without object-oriented concepts, so it only has functions. However, we can simulate object-oriented programming by creating structures (struct), and functions associated with these structures are equivalent to methods in other programming languages.</li>
|
||||
<li>Java and C# are object-oriented programming languages where code blocks (methods) are typically part of a class. Static methods behave like functions because they are bound to the class and cannot access specific instance variables.</li>
|
||||
<li>C++ and Python support both procedural programming (functions) and object-oriented programming (methods).</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="admonition question">
|
||||
<p class="admonition-title">Does the figure "Common Types of Space Complexity" reflect the absolute size of the occupied space?</p>
|
||||
<p>No, that figure shows the space complexity, which reflects the growth trend, not the absolute size of the space occupied.</p>
|
||||
<p>For example, if you take <span class="arithmatex">\(n = 8\)</span> , the values of each curve do not align with the function because each curve contains a constant term used to compress the range of values to a visually comfortable range.</p>
|
||||
<p>In practice, since we usually don't know each method's "constant term" complexity, it is generally impossible to choose the optimal solution for <span class="arithmatex">\(n = 8\)</span> based on complexity alone. But it's easier to choose for <span class="arithmatex">\(n = 8^5\)</span> as the growth trend is already dominant.</p>
|
||||
<p class="admonition-title">Does the 'Common Types of Space Complexity' figure reflect the absolute size of occupied space?</p>
|
||||
<p>No, the figure shows space complexities, which reflect growth trends, not the absolute size of the occupied space.</p>
|
||||
<p>If you take <span class="arithmatex">\(n = 8\)</span>, you might find that the values of each curve don't correspond to their functions. This is because each curve includes a constant term, intended to compress the value range into a visually comfortable range.</p>
|
||||
<p>In practice, since we usually don't know the "constant term" complexity of each method, it's generally not possible to choose the best solution for <span class="arithmatex">\(n = 8\)</span> based solely on complexity. However, for <span class="arithmatex">\(n = 8^5\)</span>, it's much easier to choose, as the growth trend becomes dominant.</p>
|
||||
</div>
|
||||
|
||||
<!-- Source file information -->
|
||||
|
|
|
@ -718,46 +718,46 @@
|
|||
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#231-trends-in-statistical-time-growth" class="md-nav__link">
|
||||
<a href="#231-assessing-time-growth-trend" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2.3.1 Trends In Statistical Time Growth
|
||||
2.3.1 Assessing Time Growth Trend
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#232-functions-asymptotic-upper-bounds" class="md-nav__link">
|
||||
<a href="#232-asymptotic-upper-bound" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2.3.2 Functions Asymptotic Upper Bounds
|
||||
2.3.2 Asymptotic Upper Bound
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#233-method-of-projection" class="md-nav__link">
|
||||
<a href="#233-calculation-method" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2.3.3 Method Of Projection
|
||||
2.3.3 Calculation Method
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<nav class="md-nav" aria-label="2.3.3 Method Of Projection">
|
||||
<nav class="md-nav" aria-label="2.3.3 Calculation Method">
|
||||
<ul class="md-nav__list">
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#1-the-first-step-counting-the-number-of-operations" class="md-nav__link">
|
||||
<a href="#1-step-1-counting-the-number-of-operations" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
1. The First Step: Counting The Number Of Operations
|
||||
1. Step 1: Counting the Number of Operations
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#2-step-2-judging-the-asymptotic-upper-bounds" class="md-nav__link">
|
||||
<a href="#2-step-2-determining-the-asymptotic-upper-bound" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2. Step 2: Judging The Asymptotic Upper Bounds
|
||||
2. Step 2: Determining the Asymptotic Upper Bound
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -769,13 +769,13 @@
|
|||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#234-common-types" class="md-nav__link">
|
||||
<a href="#234-common-types-of-time-complexity" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2.3.4 Common Types
|
||||
2.3.4 Common Types of Time Complexity
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<nav class="md-nav" aria-label="2.3.4 Common Types">
|
||||
<nav class="md-nav" aria-label="2.3.4 Common Types of Time Complexity">
|
||||
<ul class="md-nav__list">
|
||||
|
||||
<li class="md-nav__item">
|
||||
|
@ -790,16 +790,52 @@
|
|||
<li class="md-nav__item">
|
||||
<a href="#2-linear-order-on" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2. Linear Order \(O(N)\)
|
||||
2. Linear Order \(O(n)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#3-squared-order-on2" class="md-nav__link">
|
||||
<a href="#3-quadratic-order-on2" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
3. Squared Order \(O(N^2)\)
|
||||
3. Quadratic Order \(O(n^2)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#4-exponential-order-o2n" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
4. Exponential Order \(O(2^n)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#5-logarithmic-order-olog-n" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
5. Logarithmic Order \(O(\log n)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#6-linear-logarithmic-order-on-log-n" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
6. Linear-Logarithmic Order \(O(n \log n)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#7-factorial-order-on" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
7. Factorial Order \(O(n!)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -811,51 +847,9 @@
|
|||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#235-exponential-order-o2n" class="md-nav__link">
|
||||
<a href="#235-worst-best-and-average-time-complexities" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2.3.5 Exponential Order \(O(2^N)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<nav class="md-nav" aria-label="2.3.5 Exponential Order \(O(2^N)\)">
|
||||
<ul class="md-nav__list">
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#1-logarithmic-order-olog-n" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
1. Logarithmic Order \(O(\Log N)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#2-linear-logarithmic-order-on-log-n" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2. Linear Logarithmic Order \(O(N \Log N)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#3-the-factorial-order-on" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
3. The Factorial Order \(O(N!)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#236-worst-best-average-time-complexity" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2.3.6 Worst, Best, Average Time Complexity
|
||||
2.3.5 Worst, Best, and Average Time Complexities
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -946,46 +940,46 @@
|
|||
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#231-trends-in-statistical-time-growth" class="md-nav__link">
|
||||
<a href="#231-assessing-time-growth-trend" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2.3.1 Trends In Statistical Time Growth
|
||||
2.3.1 Assessing Time Growth Trend
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#232-functions-asymptotic-upper-bounds" class="md-nav__link">
|
||||
<a href="#232-asymptotic-upper-bound" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2.3.2 Functions Asymptotic Upper Bounds
|
||||
2.3.2 Asymptotic Upper Bound
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#233-method-of-projection" class="md-nav__link">
|
||||
<a href="#233-calculation-method" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2.3.3 Method Of Projection
|
||||
2.3.3 Calculation Method
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<nav class="md-nav" aria-label="2.3.3 Method Of Projection">
|
||||
<nav class="md-nav" aria-label="2.3.3 Calculation Method">
|
||||
<ul class="md-nav__list">
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#1-the-first-step-counting-the-number-of-operations" class="md-nav__link">
|
||||
<a href="#1-step-1-counting-the-number-of-operations" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
1. The First Step: Counting The Number Of Operations
|
||||
1. Step 1: Counting the Number of Operations
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#2-step-2-judging-the-asymptotic-upper-bounds" class="md-nav__link">
|
||||
<a href="#2-step-2-determining-the-asymptotic-upper-bound" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2. Step 2: Judging The Asymptotic Upper Bounds
|
||||
2. Step 2: Determining the Asymptotic Upper Bound
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -997,13 +991,13 @@
|
|||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#234-common-types" class="md-nav__link">
|
||||
<a href="#234-common-types-of-time-complexity" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2.3.4 Common Types
|
||||
2.3.4 Common Types of Time Complexity
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<nav class="md-nav" aria-label="2.3.4 Common Types">
|
||||
<nav class="md-nav" aria-label="2.3.4 Common Types of Time Complexity">
|
||||
<ul class="md-nav__list">
|
||||
|
||||
<li class="md-nav__item">
|
||||
|
@ -1018,16 +1012,52 @@
|
|||
<li class="md-nav__item">
|
||||
<a href="#2-linear-order-on" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2. Linear Order \(O(N)\)
|
||||
2. Linear Order \(O(n)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#3-squared-order-on2" class="md-nav__link">
|
||||
<a href="#3-quadratic-order-on2" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
3. Squared Order \(O(N^2)\)
|
||||
3. Quadratic Order \(O(n^2)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#4-exponential-order-o2n" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
4. Exponential Order \(O(2^n)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#5-logarithmic-order-olog-n" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
5. Logarithmic Order \(O(\log n)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#6-linear-logarithmic-order-on-log-n" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
6. Linear-Logarithmic Order \(O(n \log n)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#7-factorial-order-on" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
7. Factorial Order \(O(n!)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -1039,51 +1069,9 @@
|
|||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#235-exponential-order-o2n" class="md-nav__link">
|
||||
<a href="#235-worst-best-and-average-time-complexities" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2.3.5 Exponential Order \(O(2^N)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<nav class="md-nav" aria-label="2.3.5 Exponential Order \(O(2^N)\)">
|
||||
<ul class="md-nav__list">
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#1-logarithmic-order-olog-n" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
1. Logarithmic Order \(O(\Log N)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#2-linear-logarithmic-order-on-log-n" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2. Linear Logarithmic Order \(O(N \Log N)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#3-the-factorial-order-on" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
3. The Factorial Order \(O(N!)\)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#236-worst-best-average-time-complexity" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
2.3.6 Worst, Best, Average Time Complexity
|
||||
2.3.5 Worst, Best, and Average Time Complexities
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -1126,13 +1114,13 @@
|
|||
|
||||
<!-- Page content -->
|
||||
<h1 id="23-time-complexity">2.3 Time Complexity<a class="headerlink" href="#23-time-complexity" title="Permanent link">¶</a></h1>
|
||||
<p>Runtime can be a visual and accurate reflection of the efficiency of an algorithm. What should we do if we want to accurately predict the runtime of a piece of code?</p>
|
||||
<p>Time complexity is a concept used to measure how the run time of an algorithm increases with the size of the input data. Understanding time complexity is crucial for accurately assessing the efficiency of an algorithm.</p>
|
||||
<ol>
|
||||
<li><strong>Determine the running platform</strong>, including hardware configuration, programming language, system environment, etc., all of which affect the efficiency of the code.</li>
|
||||
<li><strong>Evaluates the running time</strong> required for various computational operations, e.g., the addition operation <code>+</code> takes 1 ns, the multiplication operation <code>*</code> takes 10 ns, the print operation <code>print()</code> takes 5 ns, and so on.</li>
|
||||
<li><strong>Counts all the computational operations in the code</strong> and sums the execution times of all the operations to get the runtime.</li>
|
||||
<li><strong>Determining the Running Platform</strong>: This includes hardware configuration, programming language, system environment, etc., all of which can affect the efficiency of code execution.</li>
|
||||
<li><strong>Evaluating the Run Time for Various Computational Operations</strong>: For instance, an addition operation <code>+</code> might take 1 ns, a multiplication operation <code>*</code> might take 10 ns, a print operation <code>print()</code> might take 5 ns, etc.</li>
|
||||
<li><strong>Counting All the Computational Operations in the Code</strong>: Summing the execution times of all these operations gives the total run time.</li>
|
||||
</ol>
|
||||
<p>For example, in the following code, the input data size is <span class="arithmatex">\(n\)</span> :</p>
|
||||
<p>For example, consider the following code with an input size of <span class="arithmatex">\(n\)</span>:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="1:12"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><input id="__tabbed_1_3" name="__tabbed_1" type="radio" /><input id="__tabbed_1_4" name="__tabbed_1" type="radio" /><input id="__tabbed_1_5" name="__tabbed_1" type="radio" /><input id="__tabbed_1_6" name="__tabbed_1" type="radio" /><input id="__tabbed_1_7" name="__tabbed_1" type="radio" /><input id="__tabbed_1_8" name="__tabbed_1" type="radio" /><input id="__tabbed_1_9" name="__tabbed_1" type="radio" /><input id="__tabbed_1_10" name="__tabbed_1" type="radio" /><input id="__tabbed_1_11" name="__tabbed_1" type="radio" /><input id="__tabbed_1_12" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">Python</label><label for="__tabbed_1_2">C++</label><label for="__tabbed_1_3">Java</label><label for="__tabbed_1_4">C#</label><label for="__tabbed_1_5">Go</label><label for="__tabbed_1_6">Swift</label><label for="__tabbed_1_7">JS</label><label for="__tabbed_1_8">TS</label><label for="__tabbed_1_9">Dart</label><label for="__tabbed_1_10">Rust</label><label for="__tabbed_1_11">C</label><label for="__tabbed_1_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -1291,14 +1279,14 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>Based on the above method, the algorithm running time can be obtained as <span class="arithmatex">\(6n + 12\)</span> ns :</p>
|
||||
<p>Using the above method, the run time of the algorithm can be calculated as <span class="arithmatex">\((6n + 12)\)</span> ns:</p>
|
||||
<div class="arithmatex">\[
|
||||
1 + 1 + 10 + (1 + 5) \times n = 6n + 12
|
||||
\]</div>
|
||||
<p>In practice, however, <strong>statistical algorithm runtimes are neither reasonable nor realistic</strong>. First, we do not want to tie the estimation time to the operation platform, because the algorithm needs to run on a variety of different platforms. Second, it is difficult for us to be informed of the runtime of each operation, which makes the prediction process extremely difficult.</p>
|
||||
<h2 id="231-trends-in-statistical-time-growth">2.3.1 Trends In Statistical Time Growth<a class="headerlink" href="#231-trends-in-statistical-time-growth" title="Permanent link">¶</a></h2>
|
||||
<p>The time complexity analysis counts not the algorithm running time, <strong>but the tendency of the algorithm running time to increase as the amount of data gets larger</strong>.</p>
|
||||
<p>The concept of "time-growing trend" is rather abstract, so let's try to understand it through an example. Suppose the size of the input data is <span class="arithmatex">\(n\)</span>, and given three algorithmic functions <code>A</code>, <code>B</code> and <code>C</code>:</p>
|
||||
<p>However, in practice, <strong>counting the run time of an algorithm is neither practical nor reasonable</strong>. First, we don't want to tie the estimated time to the running platform, as algorithms need to run on various platforms. Second, it's challenging to know the run time for each type of operation, making the estimation process difficult.</p>
|
||||
<h2 id="231-assessing-time-growth-trend">2.3.1 Assessing Time Growth Trend<a class="headerlink" href="#231-assessing-time-growth-trend" title="Permanent link">¶</a></h2>
|
||||
<p>Time complexity analysis does not count the algorithm's run time, <strong>but rather the growth trend of the run time as the data volume increases</strong>.</p>
|
||||
<p>Let's understand this concept of "time growth trend" with an example. Assume the input data size is <span class="arithmatex">\(n\)</span>, and consider three algorithms <code>A</code>, <code>B</code>, and <code>C</code>:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="2:12"><input checked="checked" id="__tabbed_2_1" name="__tabbed_2" type="radio" /><input id="__tabbed_2_2" name="__tabbed_2" type="radio" /><input id="__tabbed_2_3" name="__tabbed_2" type="radio" /><input id="__tabbed_2_4" name="__tabbed_2" type="radio" /><input id="__tabbed_2_5" name="__tabbed_2" type="radio" /><input id="__tabbed_2_6" name="__tabbed_2" type="radio" /><input id="__tabbed_2_7" name="__tabbed_2" type="radio" /><input id="__tabbed_2_8" name="__tabbed_2" type="radio" /><input id="__tabbed_2_9" name="__tabbed_2" type="radio" /><input id="__tabbed_2_10" name="__tabbed_2" type="radio" /><input id="__tabbed_2_11" name="__tabbed_2" type="radio" /><input id="__tabbed_2_12" name="__tabbed_2" type="radio" /><div class="tabbed-labels"><label for="__tabbed_2_1">Python</label><label for="__tabbed_2_2">C++</label><label for="__tabbed_2_3">Java</label><label for="__tabbed_2_4">C#</label><label for="__tabbed_2_5">Go</label><label for="__tabbed_2_6">Swift</label><label for="__tabbed_2_7">JS</label><label for="__tabbed_2_8">TS</label><label for="__tabbed_2_9">Dart</label><label for="__tabbed_2_10">Rust</label><label for="__tabbed_2_11">C</label><label for="__tabbed_2_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -1530,23 +1518,23 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>The Figure 2-7 shows the time complexity of the above three algorithmic functions.</p>
|
||||
<p>The following figure shows the time complexities of these three algorithms.</p>
|
||||
<ul>
|
||||
<li>Algorithm <code>A</code> has only <span class="arithmatex">\(1\)</span> print operations, and the running time of the algorithm does not increase with <span class="arithmatex">\(n\)</span>. We call the time complexity of this algorithm "constant order".</li>
|
||||
<li>The print operation in algorithm <code>B</code> requires <span class="arithmatex">\(n\)</span> cycles, and the running time of the algorithm increases linearly with <span class="arithmatex">\(n\)</span>. The time complexity of this algorithm is called "linear order".</li>
|
||||
<li>The print operation in algorithm <code>C</code> requires <span class="arithmatex">\(1000000\)</span> loops, which is a long runtime, but it is independent of the size of the input data <span class="arithmatex">\(n\)</span>. Therefore, the time complexity of <code>C</code> is the same as that of <code>A</code>, which is still of "constant order".</li>
|
||||
<li>Algorithm <code>A</code> has just one print operation, and its run time does not grow with <span class="arithmatex">\(n\)</span>. Its time complexity is considered "constant order."</li>
|
||||
<li>Algorithm <code>B</code> involves a print operation looping <span class="arithmatex">\(n\)</span> times, and its run time grows linearly with <span class="arithmatex">\(n\)</span>. Its time complexity is "linear order."</li>
|
||||
<li>Algorithm <code>C</code> has a print operation looping 1,000,000 times. Although it takes a long time, it is independent of the input data size <span class="arithmatex">\(n\)</span>. Therefore, the time complexity of <code>C</code> is the same as <code>A</code>, which is "constant order."</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="Time growth trends for algorithms A, B and C" class="animation-figure" src="../time_complexity.assets/time_complexity_simple_example.png" /></a></p>
|
||||
<p align="center"> Figure 2-7 Time growth trends for algorithms A, B and C </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="Time Growth Trend of Algorithms A, B, and C" class="animation-figure" src="../time_complexity.assets/time_complexity_simple_example.png" /></a></p>
|
||||
<p align="center"> Figure 2-7 Time Growth Trend of Algorithms A, B, and C </p>
|
||||
|
||||
<p>What are the characteristics of time complexity analysis compared to direct statistical algorithmic running time?</p>
|
||||
<p>Compared to directly counting the run time of an algorithm, what are the characteristics of time complexity analysis?</p>
|
||||
<ul>
|
||||
<li>The <strong>time complexity can effectively evaluate the efficiency of an algorithm</strong>. For example, the running time of algorithm <code>B</code> increases linearly and is slower than algorithm <code>A</code> for <span class="arithmatex">\(n > 1\)</span> and slower than algorithm <code>C</code> for <span class="arithmatex">\(n > 1,000,000\)</span>. In fact, as long as the input data size <span class="arithmatex">\(n\)</span> is large enough, algorithms with "constant order" of complexity will always outperform algorithms with "linear order", which is exactly what the time complexity trend means.</li>
|
||||
<li>The <strong>time complexity of the projection method is simpler</strong>. Obviously, neither the running platform nor the type of computational operation is related to the growth trend of the running time of the algorithm. Therefore, in the time complexity analysis, we can simply consider the execution time of all computation operations as the same "unit time", and thus simplify the "statistics of the running time of computation operations" to the "statistics of the number of computation operations", which is the same as the "statistics of the number of computation operations". The difficulty of the estimation is greatly reduced by considering the execution time of all operations as the same "unit time".</li>
|
||||
<li>There are also some limitations of <strong>time complexity</strong>. For example, although algorithms <code>A</code> and <code>C</code> have the same time complexity, the actual running time varies greatly. Similarly, although the time complexity of algorithm <code>B</code> is higher than that of <code>C</code> , algorithm <code>B</code> significantly outperforms algorithm <code>C</code> when the size of the input data <span class="arithmatex">\(n\)</span> is small. In these cases, it is difficult to judge the efficiency of an algorithm based on time complexity alone. Of course, despite the above problems, complexity analysis is still the most effective and commonly used method to judge the efficiency of algorithms.</li>
|
||||
<li><strong>Time complexity effectively assesses algorithm efficiency</strong>. For instance, algorithm <code>B</code> has linearly growing run time, which is slower than algorithm <code>A</code> when <span class="arithmatex">\(n > 1\)</span> and slower than <code>C</code> when <span class="arithmatex">\(n > 1,000,000\)</span>. In fact, as long as the input data size <span class="arithmatex">\(n\)</span> is sufficiently large, a "constant order" complexity algorithm will always be better than a "linear order" one, demonstrating the essence of time growth trend.</li>
|
||||
<li><strong>Time complexity analysis is more straightforward</strong>. Obviously, the running platform and the types of computational operations are irrelevant to the trend of run time growth. Therefore, in time complexity analysis, we can simply treat the execution time of all computational operations as the same "unit time," simplifying the "computational operation run time count" to a "computational operation count." This significantly reduces the complexity of estimation.</li>
|
||||
<li><strong>Time complexity has its limitations</strong>. For example, although algorithms <code>A</code> and <code>C</code> have the same time complexity, their actual run times can be quite different. Similarly, even though algorithm <code>B</code> has a higher time complexity than <code>C</code>, it is clearly superior when the input data size <span class="arithmatex">\(n\)</span> is small. In these cases, it's difficult to judge the efficiency of algorithms based solely on time complexity. Nonetheless, despite these issues, complexity analysis remains the most effective and commonly used method for evaluating algorithm efficiency.</li>
|
||||
</ul>
|
||||
<h2 id="232-functions-asymptotic-upper-bounds">2.3.2 Functions Asymptotic Upper Bounds<a class="headerlink" href="#232-functions-asymptotic-upper-bounds" title="Permanent link">¶</a></h2>
|
||||
<p>Given a function with input size <span class="arithmatex">\(n\)</span>:</p>
|
||||
<h2 id="232-asymptotic-upper-bound">2.3.2 Asymptotic Upper Bound<a class="headerlink" href="#232-asymptotic-upper-bound" title="Permanent link">¶</a></h2>
|
||||
<p>Consider a function with an input size of <span class="arithmatex">\(n\)</span>:</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>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -1694,32 +1682,31 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>Let the number of operations of the algorithm be a function of the size of the input data <span class="arithmatex">\(n\)</span>, denoted as <span class="arithmatex">\(T(n)\)</span> , then the number of operations of the above function is:</p>
|
||||
<p>Given a function that represents the number of operations of an algorithm as a function of the input size <span class="arithmatex">\(n\)</span>, denoted as <span class="arithmatex">\(T(n)\)</span>, consider the following example:</p>
|
||||
<div class="arithmatex">\[
|
||||
T(n) = 3 + 2n
|
||||
\]</div>
|
||||
<p><span class="arithmatex">\(T(n)\)</span> is a primary function, which indicates that the trend of its running time growth is linear, and thus its time complexity is of linear order.</p>
|
||||
<p>We denote the time complexity of the linear order as <span class="arithmatex">\(O(n)\)</span> , and this mathematical notation is called the "big <span class="arithmatex">\(O\)</span> notation big-<span class="arithmatex">\(O\)</span> notation", which denotes the "asymptotic upper bound" of the function <span class="arithmatex">\(T(n)\)</span>.</p>
|
||||
<p>Time complexity analysis is essentially the computation of asymptotic upper bounds on the "number of operations function <span class="arithmatex">\(T(n)\)</span>", which has a clear mathematical definition.</p>
|
||||
<p>Since <span class="arithmatex">\(T(n)\)</span> is a linear function, its growth trend is linear, and therefore, its time complexity is of linear order, denoted as <span class="arithmatex">\(O(n)\)</span>. This mathematical notation, known as "big-O notation," represents the "asymptotic upper bound" of the function <span class="arithmatex">\(T(n)\)</span>.</p>
|
||||
<p>In essence, time complexity analysis is about finding the asymptotic upper bound of the "number of operations <span class="arithmatex">\(T(n)\)</span>". It has a precise mathematical definition.</p>
|
||||
<div class="admonition abstract">
|
||||
<p class="admonition-title">Function asymptotic upper bound</p>
|
||||
<p>If there exists a positive real number <span class="arithmatex">\(c\)</span> and a real number <span class="arithmatex">\(n_0\)</span> such that <span class="arithmatex">\(T(n) \leq c \cdot f(n)\)</span> for all <span class="arithmatex">\(n > n_0\)</span> , then it can be argued that <span class="arithmatex">\(f(n)\)</span> gives an asymptotic upper bound on <span class="arithmatex">\(T(n)\)</span> , denoted as <span class="arithmatex">\(T(n) = O(f(n))\)</span> .</p>
|
||||
<p class="admonition-title">Asymptotic Upper Bound</p>
|
||||
<p>If there exist positive real numbers <span class="arithmatex">\(c\)</span> and <span class="arithmatex">\(n_0\)</span> such that for all <span class="arithmatex">\(n > n_0\)</span>, <span class="arithmatex">\(T(n) \leq c \cdot f(n)\)</span>, then <span class="arithmatex">\(f(n)\)</span> is considered an asymptotic upper bound of <span class="arithmatex">\(T(n)\)</span>, denoted as <span class="arithmatex">\(T(n) = O(f(n))\)</span>.</p>
|
||||
</div>
|
||||
<p>As shown in the Figure 2-8 , computing the asymptotic upper bound is a matter of finding a function <span class="arithmatex">\(f(n)\)</span> such that <span class="arithmatex">\(T(n)\)</span> and <span class="arithmatex">\(f(n)\)</span> are at the same growth level as <span class="arithmatex">\(n\)</span> tends to infinity, differing only by a multiple of the constant term <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="asymptotic upper bound of function" class="animation-figure" src="../time_complexity.assets/asymptotic_upper_bound.png" /></a></p>
|
||||
<p align="center"> Figure 2-8 asymptotic upper bound of function </p>
|
||||
<p>As illustrated below, calculating the asymptotic upper bound involves finding a function <span class="arithmatex">\(f(n)\)</span> such that, as <span class="arithmatex">\(n\)</span> approaches infinity, <span class="arithmatex">\(T(n)\)</span> and <span class="arithmatex">\(f(n)\)</span> have the same growth order, differing only by a constant factor <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="Asymptotic Upper Bound of a Function" class="animation-figure" src="../time_complexity.assets/asymptotic_upper_bound.png" /></a></p>
|
||||
<p align="center"> Figure 2-8 Asymptotic Upper Bound of a Function </p>
|
||||
|
||||
<h2 id="233-method-of-projection">2.3.3 Method Of Projection<a class="headerlink" href="#233-method-of-projection" title="Permanent link">¶</a></h2>
|
||||
<p>Asymptotic upper bounds are a bit heavy on math, so don't worry if you feel you don't have a full solution. Because in practice, we only need to master the projection method, and the mathematical meaning can be gradually comprehended.</p>
|
||||
<p>By definition, after determining <span class="arithmatex">\(f(n)\)</span>, we can get the time complexity <span class="arithmatex">\(O(f(n))\)</span>. So how to determine the asymptotic upper bound <span class="arithmatex">\(f(n)\)</span>? The overall is divided into two steps: first count the number of operations, and then determine the asymptotic upper bound.</p>
|
||||
<h3 id="1-the-first-step-counting-the-number-of-operations">1. The First Step: Counting The Number Of Operations<a class="headerlink" href="#1-the-first-step-counting-the-number-of-operations" title="Permanent link">¶</a></h3>
|
||||
<p>For the code, it is sufficient to calculate from top to bottom line by line. However, since the constant term <span class="arithmatex">\(c \cdot f(n)\)</span> in the above <span class="arithmatex">\(c \cdot f(n)\)</span> can take any size, <strong>the various coefficients and constant terms in the number of operations <span class="arithmatex">\(T(n)\)</span> can be ignored</strong>. Based on this principle, the following counting simplification techniques can be summarized.</p>
|
||||
<h2 id="233-calculation-method">2.3.3 Calculation Method<a class="headerlink" href="#233-calculation-method" title="Permanent link">¶</a></h2>
|
||||
<p>While the concept of asymptotic upper bound might seem mathematically dense, you don't need to fully grasp it right away. Let's first understand the method of calculation, which can be practiced and comprehended over time.</p>
|
||||
<p>Once <span class="arithmatex">\(f(n)\)</span> is determined, we obtain the time complexity <span class="arithmatex">\(O(f(n))\)</span>. But how do we determine the asymptotic upper bound <span class="arithmatex">\(f(n)\)</span>? This process generally involves two steps: counting the number of operations and determining the asymptotic upper bound.</p>
|
||||
<h3 id="1-step-1-counting-the-number-of-operations">1. Step 1: Counting the Number of Operations<a class="headerlink" href="#1-step-1-counting-the-number-of-operations" title="Permanent link">¶</a></h3>
|
||||
<p>This step involves going through the code line by line. However, due to the presence of the constant <span class="arithmatex">\(c\)</span> in <span class="arithmatex">\(c \cdot f(n)\)</span>, <strong>all coefficients and constant terms in <span class="arithmatex">\(T(n)\)</span> can be ignored</strong>. This principle allows for simplification techniques in counting operations.</p>
|
||||
<ol>
|
||||
<li><strong>Ignore the constant terms in <span class="arithmatex">\(T(n)\)</span></strong>. Since none of them are related to <span class="arithmatex">\(n\)</span>, they have no effect on the time complexity.</li>
|
||||
<li><strong>omits all coefficients</strong>. For example, loops <span class="arithmatex">\(2n\)</span> times, <span class="arithmatex">\(5n + 1\)</span> times, etc., can be simplified and notated as <span class="arithmatex">\(n\)</span> times because the coefficients before <span class="arithmatex">\(n\)</span> have no effect on the time complexity.</li>
|
||||
<li><strong>Use multiplication</strong> when loops are nested. The total number of operations is equal to the product of the number of operations of the outer and inner levels of the loop, and each level of the loop can still be nested by applying the techniques in points <code>1.</code> and <code>2.</code> respectively.</li>
|
||||
<li><strong>Ignore constant terms in <span class="arithmatex">\(T(n)\)</span></strong>, as they do not affect the time complexity being independent of <span class="arithmatex">\(n\)</span>.</li>
|
||||
<li><strong>Omit all coefficients</strong>. For example, looping <span class="arithmatex">\(2n\)</span>, <span class="arithmatex">\(5n + 1\)</span> times, etc., can be simplified to <span class="arithmatex">\(n\)</span> times since the coefficient before <span class="arithmatex">\(n\)</span> does not impact the time complexity.</li>
|
||||
<li><strong>Use multiplication for nested loops</strong>. The total number of operations equals the product of the number of operations in each loop, applying the simplification techniques from points 1 and 2 for each loop level.</li>
|
||||
</ol>
|
||||
<p>Given a function, we can use the above trick to count the number of operations.</p>
|
||||
<p>Given a function, we can use these techniques to count operations:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="4:12"><input checked="checked" id="__tabbed_4_1" name="__tabbed_4" type="radio" /><input id="__tabbed_4_2" name="__tabbed_4" type="radio" /><input id="__tabbed_4_3" name="__tabbed_4" type="radio" /><input id="__tabbed_4_4" name="__tabbed_4" type="radio" /><input id="__tabbed_4_5" name="__tabbed_4" type="radio" /><input id="__tabbed_4_6" name="__tabbed_4" type="radio" /><input id="__tabbed_4_7" name="__tabbed_4" type="radio" /><input id="__tabbed_4_8" name="__tabbed_4" type="radio" /><input id="__tabbed_4_9" name="__tabbed_4" type="radio" /><input id="__tabbed_4_10" name="__tabbed_4" type="radio" /><input id="__tabbed_4_11" name="__tabbed_4" type="radio" /><input id="__tabbed_4_12" name="__tabbed_4" type="radio" /><div class="tabbed-labels"><label for="__tabbed_4_1">Python</label><label for="__tabbed_4_2">C++</label><label for="__tabbed_4_3">Java</label><label for="__tabbed_4_4">C#</label><label for="__tabbed_4_5">Go</label><label for="__tabbed_4_6">Swift</label><label for="__tabbed_4_7">JS</label><label for="__tabbed_4_8">TS</label><label for="__tabbed_4_9">Dart</label><label for="__tabbed_4_10">Rust</label><label for="__tabbed_4_11">C</label><label for="__tabbed_4_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -1928,25 +1915,25 @@ T(n) = 3 + 2n
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>The following equations show the statistical results before and after using the above technique, both of which were introduced with a time complexity of <span class="arithmatex">\(O(n^2)\)</span> .</p>
|
||||
<p>The formula below shows the counting results before and after simplification, both leading to a time complexity of <span class="arithmatex">\(O(n^2)\)</span>:</p>
|
||||
<div class="arithmatex">\[
|
||||
\begin{aligned}
|
||||
T(n) & = 2n(n + 1) + (5n + 1) + 2 & \text{complete statistics (-.-|||)} \newline
|
||||
T(n) & = 2n(n + 1) + (5n + 1) + 2 & \text{Complete Count (-.-|||)} \newline
|
||||
& = 2n^2 + 7n + 3 \newline
|
||||
T(n) & = n^2 + n & \text{Lazy Stats (o.O)}
|
||||
T(n) & = n^2 + n & \text{Simplified Count (o.O)}
|
||||
\end{aligned}
|
||||
\]</div>
|
||||
<h3 id="2-step-2-judging-the-asymptotic-upper-bounds">2. Step 2: Judging The Asymptotic Upper Bounds<a class="headerlink" href="#2-step-2-judging-the-asymptotic-upper-bounds" title="Permanent link">¶</a></h3>
|
||||
<p><strong>The time complexity is determined by the highest order term in the polynomial <span class="arithmatex">\(T(n)\)</span></strong>. This is because as <span class="arithmatex">\(n\)</span> tends to infinity, the highest order term will play a dominant role and the effects of all other terms can be ignored.</p>
|
||||
<p>The Table 2-2 shows some examples, some of which have exaggerated values to emphasize the conclusion that "the coefficients can't touch the order". As <span class="arithmatex">\(n\)</span> tends to infinity, these constants become irrelevant.</p>
|
||||
<p align="center"> Table 2-2 Time complexity corresponding to different number of operations </p>
|
||||
<h3 id="2-step-2-determining-the-asymptotic-upper-bound">2. Step 2: Determining the Asymptotic Upper Bound<a class="headerlink" href="#2-step-2-determining-the-asymptotic-upper-bound" title="Permanent link">¶</a></h3>
|
||||
<p><strong>The time complexity is determined by the highest order term in <span class="arithmatex">\(T(n)\)</span></strong>. This is because, as <span class="arithmatex">\(n\)</span> approaches infinity, the highest order term dominates, rendering the influence of other terms negligible.</p>
|
||||
<p>The following table illustrates examples of different operation counts and their corresponding time complexities. Some exaggerated values are used to emphasize that coefficients cannot alter the order of growth. When <span class="arithmatex">\(n\)</span> becomes very large, these constants become insignificant.</p>
|
||||
<p align="center"> Table: Time Complexity for Different Operation Counts </p>
|
||||
|
||||
<div class="center-table">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>number of operations <span class="arithmatex">\(T(n)\)</span></th>
|
||||
<th>time complexity <span class="arithmatex">\(O(f(n))\)</span></th>
|
||||
<th>Operation Count <span class="arithmatex">\(T(n)\)</span></th>
|
||||
<th>Time Complexity <span class="arithmatex">\(O(f(n))\)</span></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -1973,20 +1960,19 @@ T(n) & = n^2 + n & \text{Lazy Stats (o.O)}
|
|||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<h2 id="234-common-types">2.3.4 Common Types<a class="headerlink" href="#234-common-types" title="Permanent link">¶</a></h2>
|
||||
<p>Let the input data size be <span class="arithmatex">\(n\)</span> , the common types of time complexity are shown in the Figure 2-9 (in descending order).</p>
|
||||
<h2 id="234-common-types-of-time-complexity">2.3.4 Common Types of Time Complexity<a class="headerlink" href="#234-common-types-of-time-complexity" title="Permanent link">¶</a></h2>
|
||||
<p>Let's consider the input data size as <span class="arithmatex">\(n\)</span>. The common types of time complexities are illustrated below, arranged from lowest to highest:</p>
|
||||
<div class="arithmatex">\[
|
||||
\begin{aligned}
|
||||
O(1) < O(\log n) < O(n) < O(n \log n) < O(n^2) < O(2^n) < O(n!) \newline
|
||||
\text{constant order} < \text{logarithmic order} < \text{linear order} < \text{linear logarithmic order} < \text{square order} < \text{exponential order} < \text{multiplication order}
|
||||
\text{Constant Order} < \text{Logarithmic Order} < \text{Linear Order} < \text{Linear-Logarithmic Order} < \text{Quadratic Order} < \text{Exponential Order} < \text{Factorial Order}
|
||||
\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="Common time complexity types" class="animation-figure" src="../time_complexity.assets/time_complexity_common_types.png" /></a></p>
|
||||
<p align="center"> Figure 2-9 Common time complexity types </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="Common Types of Time Complexity" class="animation-figure" src="../time_complexity.assets/time_complexity_common_types.png" /></a></p>
|
||||
<p align="center"> Figure 2-9 Common Types of Time Complexity </p>
|
||||
|
||||
<h3 id="1-constant-order-o1">1. Constant Order <span class="arithmatex">\(O(1)\)</span><a class="headerlink" href="#1-constant-order-o1" title="Permanent link">¶</a></h3>
|
||||
<p>The number of operations of the constant order is independent of the input data size <span class="arithmatex">\(n\)</span>, i.e., it does not change with <span class="arithmatex">\(n\)</span>.</p>
|
||||
<p>In the following function, although the number of operations <code>size</code> may be large, the time complexity is still <span class="arithmatex">\(O(1)\)</span> because it is independent of the input data size <span class="arithmatex">\(n\)</span> :</p>
|
||||
<p>Constant order means the number of operations is independent of the input data size <span class="arithmatex">\(n\)</span>. In the following function, although the number of operations <code>size</code> might be large, the time complexity remains <span class="arithmatex">\(O(1)\)</span> as it's unrelated to <span class="arithmatex">\(n\)</span>:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="5:12"><input checked="checked" id="__tabbed_5_1" name="__tabbed_5" type="radio" /><input id="__tabbed_5_2" name="__tabbed_5" type="radio" /><input id="__tabbed_5_3" name="__tabbed_5" type="radio" /><input id="__tabbed_5_4" name="__tabbed_5" type="radio" /><input id="__tabbed_5_5" name="__tabbed_5" type="radio" /><input id="__tabbed_5_6" name="__tabbed_5" type="radio" /><input id="__tabbed_5_7" name="__tabbed_5" type="radio" /><input id="__tabbed_5_8" name="__tabbed_5" type="radio" /><input id="__tabbed_5_9" name="__tabbed_5" type="radio" /><input id="__tabbed_5_10" name="__tabbed_5" type="radio" /><input id="__tabbed_5_11" name="__tabbed_5" type="radio" /><input id="__tabbed_5_12" name="__tabbed_5" type="radio" /><div class="tabbed-labels"><label for="__tabbed_5_1">Python</label><label for="__tabbed_5_2">C++</label><label for="__tabbed_5_3">Java</label><label for="__tabbed_5_4">C#</label><label for="__tabbed_5_5">Go</label><label for="__tabbed_5_6">Swift</label><label for="__tabbed_5_7">JS</label><label for="__tabbed_5_8">TS</label><label for="__tabbed_5_9">Dart</label><label for="__tabbed_5_10">Rust</label><label for="__tabbed_5_11">C</label><label for="__tabbed_5_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -2130,8 +2116,8 @@ O(1) < O(\log n) < O(n) < O(n \log n) < O(n^2) < O(2^n) < O(n!
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h3 id="2-linear-order-on">2. Linear Order <span class="arithmatex">\(O(N)\)</span><a class="headerlink" href="#2-linear-order-on" title="Permanent link">¶</a></h3>
|
||||
<p>The number of operations in a linear order grows in linear steps relative to the input data size <span class="arithmatex">\(n\)</span>. Linear orders are usually found in single level loops:</p>
|
||||
<h3 id="2-linear-order-on">2. Linear Order <span class="arithmatex">\(O(n)\)</span><a class="headerlink" href="#2-linear-order-on" title="Permanent link">¶</a></h3>
|
||||
<p>Linear order indicates the number of operations grows linearly with the input data size <span class="arithmatex">\(n\)</span>. Linear order commonly appears in single-loop structures:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="6:12"><input checked="checked" id="__tabbed_6_1" name="__tabbed_6" type="radio" /><input id="__tabbed_6_2" name="__tabbed_6" type="radio" /><input id="__tabbed_6_3" name="__tabbed_6" type="radio" /><input id="__tabbed_6_4" name="__tabbed_6" type="radio" /><input id="__tabbed_6_5" name="__tabbed_6" type="radio" /><input id="__tabbed_6_6" name="__tabbed_6" type="radio" /><input id="__tabbed_6_7" name="__tabbed_6" type="radio" /><input id="__tabbed_6_8" name="__tabbed_6" type="radio" /><input id="__tabbed_6_9" name="__tabbed_6" type="radio" /><input id="__tabbed_6_10" name="__tabbed_6" type="radio" /><input id="__tabbed_6_11" name="__tabbed_6" type="radio" /><input id="__tabbed_6_12" name="__tabbed_6" type="radio" /><div class="tabbed-labels"><label for="__tabbed_6_1">Python</label><label for="__tabbed_6_2">C++</label><label for="__tabbed_6_3">Java</label><label for="__tabbed_6_4">C#</label><label for="__tabbed_6_5">Go</label><label for="__tabbed_6_6">Swift</label><label for="__tabbed_6_7">JS</label><label for="__tabbed_6_8">TS</label><label for="__tabbed_6_9">Dart</label><label for="__tabbed_6_10">Rust</label><label for="__tabbed_6_11">C</label><label for="__tabbed_6_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -2260,7 +2246,7 @@ O(1) < O(\log n) < O(n) < O(n \log n) < O(n^2) < O(2^n) < O(n!
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>The time complexity of operations such as traversing an array and traversing a linked list is <span class="arithmatex">\(O(n)\)</span> , where <span class="arithmatex">\(n\)</span> is the length of the array or linked list:</p>
|
||||
<p>Operations like array traversal and linked list traversal have a time complexity of <span class="arithmatex">\(O(n)\)</span>, where <span class="arithmatex">\(n\)</span> is the length of the array or list:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="7:12"><input checked="checked" id="__tabbed_7_1" name="__tabbed_7" type="radio" /><input id="__tabbed_7_2" name="__tabbed_7" type="radio" /><input id="__tabbed_7_3" name="__tabbed_7" type="radio" /><input id="__tabbed_7_4" name="__tabbed_7" type="radio" /><input id="__tabbed_7_5" name="__tabbed_7" type="radio" /><input id="__tabbed_7_6" name="__tabbed_7" type="radio" /><input id="__tabbed_7_7" name="__tabbed_7" type="radio" /><input id="__tabbed_7_8" name="__tabbed_7" type="radio" /><input id="__tabbed_7_9" name="__tabbed_7" type="radio" /><input id="__tabbed_7_10" name="__tabbed_7" type="radio" /><input id="__tabbed_7_11" name="__tabbed_7" type="radio" /><input id="__tabbed_7_12" name="__tabbed_7" type="radio" /><div class="tabbed-labels"><label for="__tabbed_7_1">Python</label><label for="__tabbed_7_2">C++</label><label for="__tabbed_7_3">Java</label><label for="__tabbed_7_4">C#</label><label for="__tabbed_7_5">Go</label><label for="__tabbed_7_6">Swift</label><label for="__tabbed_7_7">JS</label><label for="__tabbed_7_8">TS</label><label for="__tabbed_7_9">Dart</label><label for="__tabbed_7_10">Rust</label><label for="__tabbed_7_11">C</label><label for="__tabbed_7_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -2407,9 +2393,9 @@ O(1) < O(\log n) < O(n) < O(n \log n) < O(n^2) < O(2^n) < O(n!
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>It is worth noting that <strong>Input data size <span class="arithmatex">\(n\)</span> needs to be determined specifically</strong> according to the type of input data. For example, in the first example, the variable <span class="arithmatex">\(n\)</span> is the input data size; in the second example, the array length <span class="arithmatex">\(n\)</span> is the data size.</p>
|
||||
<h3 id="3-squared-order-on2">3. Squared Order <span class="arithmatex">\(O(N^2)\)</span><a class="headerlink" href="#3-squared-order-on2" title="Permanent link">¶</a></h3>
|
||||
<p>The number of operations in the square order grows in square steps with respect to the size of the input data <span class="arithmatex">\(n\)</span>. The squared order is usually found in nested loops, where both the outer and inner levels are <span class="arithmatex">\(O(n)\)</span> and therefore overall <span class="arithmatex">\(O(n^2)\)</span>:</p>
|
||||
<p>It's important to note that <strong>the input data size <span class="arithmatex">\(n\)</span> should be determined based on the type of input data</strong>. For example, in the first example, <span class="arithmatex">\(n\)</span> represents the input data size, while in the second example, the length of the array <span class="arithmatex">\(n\)</span> is the data size.</p>
|
||||
<h3 id="3-quadratic-order-on2">3. Quadratic Order <span class="arithmatex">\(O(n^2)\)</span><a class="headerlink" href="#3-quadratic-order-on2" title="Permanent link">¶</a></h3>
|
||||
<p>Quadratic order means the number of operations grows quadratically with the input data size <span class="arithmatex">\(n\)</span>. Quadratic order typically appears in nested loops, where both the outer and inner loops have a time complexity of <span class="arithmatex">\(O(n)\)</span>, resulting in an overall complexity of <span class="arithmatex">\(O(n^2)\)</span>:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="8:12"><input checked="checked" id="__tabbed_8_1" name="__tabbed_8" type="radio" /><input id="__tabbed_8_2" name="__tabbed_8" type="radio" /><input id="__tabbed_8_3" name="__tabbed_8" type="radio" /><input id="__tabbed_8_4" name="__tabbed_8" type="radio" /><input id="__tabbed_8_5" name="__tabbed_8" type="radio" /><input id="__tabbed_8_6" name="__tabbed_8" type="radio" /><input id="__tabbed_8_7" name="__tabbed_8" type="radio" /><input id="__tabbed_8_8" name="__tabbed_8" type="radio" /><input id="__tabbed_8_9" name="__tabbed_8" type="radio" /><input id="__tabbed_8_10" name="__tabbed_8" type="radio" /><input id="__tabbed_8_11" name="__tabbed_8" type="radio" /><input id="__tabbed_8_12" name="__tabbed_8" type="radio" /><div class="tabbed-labels"><label for="__tabbed_8_1">Python</label><label for="__tabbed_8_2">C++</label><label for="__tabbed_8_3">Java</label><label for="__tabbed_8_4">C#</label><label for="__tabbed_8_5">Go</label><label for="__tabbed_8_6">Swift</label><label for="__tabbed_8_7">JS</label><label for="__tabbed_8_8">TS</label><label for="__tabbed_8_9">Dart</label><label for="__tabbed_8_10">Rust</label><label for="__tabbed_8_11">C</label><label for="__tabbed_8_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -2581,11 +2567,11 @@ O(1) < O(\log n) < O(n) < O(n \log n) < O(n^2) < O(2^n) < O(n!
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>The Figure 2-10 compares the three time complexities of constant order, linear order and squared order.</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="Time complexity of constant, linear and quadratic orders" class="animation-figure" src="../time_complexity.assets/time_complexity_constant_linear_quadratic.png" /></a></p>
|
||||
<p align="center"> Figure 2-10 Time complexity of constant, linear and quadratic orders </p>
|
||||
<p>The following image compares constant order, linear order, and quadratic order time complexities.</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="Constant, Linear, and Quadratic Order Time Complexities" class="animation-figure" src="../time_complexity.assets/time_complexity_constant_linear_quadratic.png" /></a></p>
|
||||
<p align="center"> Figure 2-10 Constant, Linear, and Quadratic Order Time Complexities </p>
|
||||
|
||||
<p>Taking bubble sort as an example, the outer loop executes <span class="arithmatex">\(n - 1\)</span> times, and the inner loop executes <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> times, which averages out to <span class="arithmatex">\(n / 2\)</span> times, resulting in a time complexity of <span class="arithmatex">\(O((n - 1) n / 2) = O(n^2)\)</span> .</p>
|
||||
<p>For instance, in bubble sort, the outer loop runs <span class="arithmatex">\(n - 1\)</span> times, and the inner loop runs <span class="arithmatex">\(n-1\)</span>, <span class="arithmatex">\(n-2\)</span>, ..., <span class="arithmatex">\(2\)</span>, <span class="arithmatex">\(1\)</span> times, averaging <span class="arithmatex">\(n / 2\)</span> times, resulting in a time complexity of <span class="arithmatex">\(O((n - 1) n / 2) = O(n^2)\)</span>:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="9:12"><input checked="checked" id="__tabbed_9_1" name="__tabbed_9" type="radio" /><input id="__tabbed_9_2" name="__tabbed_9" type="radio" /><input id="__tabbed_9_3" name="__tabbed_9" type="radio" /><input id="__tabbed_9_4" name="__tabbed_9" type="radio" /><input id="__tabbed_9_5" name="__tabbed_9" type="radio" /><input id="__tabbed_9_6" name="__tabbed_9" type="radio" /><input id="__tabbed_9_7" name="__tabbed_9" type="radio" /><input id="__tabbed_9_8" name="__tabbed_9" type="radio" /><input id="__tabbed_9_9" name="__tabbed_9" type="radio" /><input id="__tabbed_9_10" name="__tabbed_9" type="radio" /><input id="__tabbed_9_11" name="__tabbed_9" type="radio" /><input id="__tabbed_9_12" name="__tabbed_9" type="radio" /><div class="tabbed-labels"><label for="__tabbed_9_1">Python</label><label for="__tabbed_9_2">C++</label><label for="__tabbed_9_3">Java</label><label for="__tabbed_9_4">C#</label><label for="__tabbed_9_5">Go</label><label for="__tabbed_9_6">Swift</label><label for="__tabbed_9_7">JS</label><label for="__tabbed_9_8">TS</label><label for="__tabbed_9_9">Dart</label><label for="__tabbed_9_10">Rust</label><label for="__tabbed_9_11">C</label><label for="__tabbed_9_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -2838,9 +2824,9 @@ O(1) < O(\log n) < O(n) < O(n \log n) < O(n^2) < O(2^n) < O(n!
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2 id="235-exponential-order-o2n">2.3.5 Exponential Order <span class="arithmatex">\(O(2^N)\)</span><a class="headerlink" href="#235-exponential-order-o2n" title="Permanent link">¶</a></h2>
|
||||
<p>Cell division in biology is a typical example of exponential growth: the initial state is <span class="arithmatex">\(1\)</span> cells, after one round of division it becomes <span class="arithmatex">\(2\)</span>, after two rounds of division it becomes <span class="arithmatex">\(4\)</span>, and so on, after <span class="arithmatex">\(n\)</span> rounds of division there are <span class="arithmatex">\(2^n\)</span> cells.</p>
|
||||
<p>The Figure 2-11 and the following code simulate the process of cell division with a time complexity of <span class="arithmatex">\(O(2^n)\)</span> .</p>
|
||||
<h3 id="4-exponential-order-o2n">4. Exponential Order <span class="arithmatex">\(O(2^n)\)</span><a class="headerlink" href="#4-exponential-order-o2n" title="Permanent link">¶</a></h3>
|
||||
<p>Biological "cell division" is a classic example of exponential order growth: starting with one cell, it becomes two after one division, four after two divisions, and so on, resulting in <span class="arithmatex">\(2^n\)</span> cells after <span class="arithmatex">\(n\)</span> divisions.</p>
|
||||
<p>The following image and code simulate the cell division process, with a time complexity of <span class="arithmatex">\(O(2^n)\)</span>:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="10:12"><input checked="checked" id="__tabbed_10_1" name="__tabbed_10" type="radio" /><input id="__tabbed_10_2" name="__tabbed_10" type="radio" /><input id="__tabbed_10_3" name="__tabbed_10" type="radio" /><input id="__tabbed_10_4" name="__tabbed_10" type="radio" /><input id="__tabbed_10_5" name="__tabbed_10" type="radio" /><input id="__tabbed_10_6" name="__tabbed_10" type="radio" /><input id="__tabbed_10_7" name="__tabbed_10" type="radio" /><input id="__tabbed_10_8" name="__tabbed_10" type="radio" /><input id="__tabbed_10_9" name="__tabbed_10" type="radio" /><input id="__tabbed_10_10" name="__tabbed_10" type="radio" /><input id="__tabbed_10_11" name="__tabbed_10" type="radio" /><input id="__tabbed_10_12" name="__tabbed_10" type="radio" /><div class="tabbed-labels"><label for="__tabbed_10_1">Python</label><label for="__tabbed_10_2">C++</label><label for="__tabbed_10_3">Java</label><label for="__tabbed_10_4">C#</label><label for="__tabbed_10_5">Go</label><label for="__tabbed_10_6">Swift</label><label for="__tabbed_10_7">JS</label><label for="__tabbed_10_8">TS</label><label for="__tabbed_10_9">Dart</label><label for="__tabbed_10_10">Rust</label><label for="__tabbed_10_11">C</label><label for="__tabbed_10_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -3043,10 +3029,10 @@ 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="time complexity of exponential order" class="animation-figure" src="../time_complexity.assets/time_complexity_exponential.png" /></a></p>
|
||||
<p align="center"> Figure 2-11 time complexity of exponential order </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="Exponential Order Time Complexity" class="animation-figure" src="../time_complexity.assets/time_complexity_exponential.png" /></a></p>
|
||||
<p align="center"> Figure 2-11 Exponential Order Time Complexity </p>
|
||||
|
||||
<p>In practical algorithms, exponential orders are often found in recursion functions. For example, in the following code, it recursively splits in two and stops after <span class="arithmatex">\(n\)</span> splits:</p>
|
||||
<p>In practice, exponential order often appears in recursive functions. For example, in the code below, it recursively splits into two halves, stopping after <span class="arithmatex">\(n\)</span> divisions:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="11:12"><input checked="checked" id="__tabbed_11_1" name="__tabbed_11" type="radio" /><input id="__tabbed_11_2" name="__tabbed_11" type="radio" /><input id="__tabbed_11_3" name="__tabbed_11" type="radio" /><input id="__tabbed_11_4" name="__tabbed_11" type="radio" /><input id="__tabbed_11_5" name="__tabbed_11" type="radio" /><input id="__tabbed_11_6" name="__tabbed_11" type="radio" /><input id="__tabbed_11_7" name="__tabbed_11" type="radio" /><input id="__tabbed_11_8" name="__tabbed_11" type="radio" /><input id="__tabbed_11_9" name="__tabbed_11" type="radio" /><input id="__tabbed_11_10" name="__tabbed_11" type="radio" /><input id="__tabbed_11_11" name="__tabbed_11" type="radio" /><input id="__tabbed_11_12" name="__tabbed_11" type="radio" /><div class="tabbed-labels"><label for="__tabbed_11_1">Python</label><label for="__tabbed_11_2">C++</label><label for="__tabbed_11_3">Java</label><label for="__tabbed_11_4">C#</label><label for="__tabbed_11_5">Go</label><label for="__tabbed_11_6">Swift</label><label for="__tabbed_11_7">JS</label><label for="__tabbed_11_8">TS</label><label for="__tabbed_11_9">Dart</label><label for="__tabbed_11_10">Rust</label><label for="__tabbed_11_11">C</label><label for="__tabbed_11_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -3156,10 +3142,10 @@ O(1) < O(\log n) < O(n) < O(n \log n) < O(n^2) < O(2^n) < O(n!
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>Exponential order grows very rapidly and is more common in exhaustive methods (brute force search, backtracking, etc.). For problems with large data sizes, exponential order is unacceptable and usually requires the use of algorithms such as dynamic programming or greedy algorithms to solve.</p>
|
||||
<h3 id="1-logarithmic-order-olog-n">1. Logarithmic Order <span class="arithmatex">\(O(\Log N)\)</span><a class="headerlink" href="#1-logarithmic-order-olog-n" title="Permanent link">¶</a></h3>
|
||||
<p>In contrast to the exponential order, the logarithmic order reflects the "each round is reduced to half" case. Let the input data size be <span class="arithmatex">\(n\)</span>, and since each round is reduced to half, the number of loops is <span class="arithmatex">\(\log_2 n\)</span>, which is the inverse function of <span class="arithmatex">\(2^n\)</span>.</p>
|
||||
<p>The Figure 2-12 and the code below simulate the process of "reducing each round to half" with a time complexity of <span class="arithmatex">\(O(\log_2 n)\)</span>, which is abbreviated as <span class="arithmatex">\(O(\log n)\)</span>.</p>
|
||||
<p>Exponential order growth is extremely rapid and is commonly seen in exhaustive search methods (brute force, backtracking, etc.). For large-scale problems, exponential order is unacceptable, often requiring dynamic programming or greedy algorithms as solutions.</p>
|
||||
<h3 id="5-logarithmic-order-olog-n">5. Logarithmic Order <span class="arithmatex">\(O(\log n)\)</span><a class="headerlink" href="#5-logarithmic-order-olog-n" title="Permanent link">¶</a></h3>
|
||||
<p>In contrast to exponential order, logarithmic order reflects situations where "the size is halved each round." Given an input data size <span class="arithmatex">\(n\)</span>, since the size is halved each round, the number of iterations is <span class="arithmatex">\(\log_2 n\)</span>, the inverse function of <span class="arithmatex">\(2^n\)</span>.</p>
|
||||
<p>The following image and code simulate the "halving each round" process, with a time complexity of <span class="arithmatex">\(O(\log_2 n)\)</span>, commonly abbreviated as <span class="arithmatex">\(O(\log n)\)</span>:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="12:12"><input checked="checked" id="__tabbed_12_1" name="__tabbed_12" type="radio" /><input id="__tabbed_12_2" name="__tabbed_12" type="radio" /><input id="__tabbed_12_3" name="__tabbed_12" type="radio" /><input id="__tabbed_12_4" name="__tabbed_12" type="radio" /><input id="__tabbed_12_5" name="__tabbed_12" type="radio" /><input id="__tabbed_12_6" name="__tabbed_12" type="radio" /><input id="__tabbed_12_7" name="__tabbed_12" type="radio" /><input id="__tabbed_12_8" name="__tabbed_12" type="radio" /><input id="__tabbed_12_9" name="__tabbed_12" type="radio" /><input id="__tabbed_12_10" name="__tabbed_12" type="radio" /><input id="__tabbed_12_11" name="__tabbed_12" type="radio" /><input id="__tabbed_12_12" name="__tabbed_12" type="radio" /><div class="tabbed-labels"><label for="__tabbed_12_1">Python</label><label for="__tabbed_12_2">C++</label><label for="__tabbed_12_3">Java</label><label for="__tabbed_12_4">C#</label><label for="__tabbed_12_5">Go</label><label for="__tabbed_12_6">Swift</label><label for="__tabbed_12_7">JS</label><label for="__tabbed_12_8">TS</label><label for="__tabbed_12_9">Dart</label><label for="__tabbed_12_10">Rust</label><label for="__tabbed_12_11">C</label><label for="__tabbed_12_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -3309,10 +3295,10 @@ 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="time complexity of logarithmic order" class="animation-figure" src="../time_complexity.assets/time_complexity_logarithmic.png" /></a></p>
|
||||
<p align="center"> Figure 2-12 time complexity of logarithmic order </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="Logarithmic Order Time Complexity" class="animation-figure" src="../time_complexity.assets/time_complexity_logarithmic.png" /></a></p>
|
||||
<p align="center"> Figure 2-12 Logarithmic Order Time Complexity </p>
|
||||
|
||||
<p>Similar to the exponential order, the logarithmic order is often found in recursion functions. The following code forms a recursion tree of height <span class="arithmatex">\(\log_2 n\)</span>:</p>
|
||||
<p>Like exponential order, logarithmic order also frequently appears in recursive functions. The code below forms a recursive tree of height <span class="arithmatex">\(\log_2 n\)</span>:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="13:12"><input checked="checked" id="__tabbed_13_1" name="__tabbed_13" type="radio" /><input id="__tabbed_13_2" name="__tabbed_13" type="radio" /><input id="__tabbed_13_3" name="__tabbed_13" type="radio" /><input id="__tabbed_13_4" name="__tabbed_13" type="radio" /><input id="__tabbed_13_5" name="__tabbed_13" type="radio" /><input id="__tabbed_13_6" name="__tabbed_13" type="radio" /><input id="__tabbed_13_7" name="__tabbed_13" type="radio" /><input id="__tabbed_13_8" name="__tabbed_13" type="radio" /><input id="__tabbed_13_9" name="__tabbed_13" type="radio" /><input id="__tabbed_13_10" name="__tabbed_13" type="radio" /><input id="__tabbed_13_11" name="__tabbed_13" type="radio" /><input id="__tabbed_13_12" name="__tabbed_13" type="radio" /><div class="tabbed-labels"><label for="__tabbed_13_1">Python</label><label for="__tabbed_13_2">C++</label><label for="__tabbed_13_3">Java</label><label for="__tabbed_13_4">C#</label><label for="__tabbed_13_5">Go</label><label for="__tabbed_13_6">Swift</label><label for="__tabbed_13_7">JS</label><label for="__tabbed_13_8">TS</label><label for="__tabbed_13_9">Dart</label><label for="__tabbed_13_10">Rust</label><label for="__tabbed_13_11">C</label><label for="__tabbed_13_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -3422,17 +3408,17 @@ O(1) < O(\log n) < O(n) < O(n \log n) < O(n^2) < O(2^n) < O(n!
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>Logarithmic order is often found in algorithms based on the divide and conquer strategy, which reflects the algorithmic ideas of "dividing one into many" and "simplifying the complexity into simplicity". It grows slowly and is the second most desirable time complexity after constant order.</p>
|
||||
<p>Logarithmic order is typical in algorithms based on the divide-and-conquer strategy, embodying the "split into many" and "simplify complex problems" approach. It's slow-growing and is the most ideal time complexity after constant order.</p>
|
||||
<div class="admonition tip">
|
||||
<p class="admonition-title">What is the base of <span class="arithmatex">\(O(\log n)\)</span>?</p>
|
||||
<p>To be precise, the corresponding time complexity of "one divided into <span class="arithmatex">\(m\)</span>" is <span class="arithmatex">\(O(\log_m n)\)</span> . And by using the logarithmic permutation formula, we can get equal time complexity with different bases:</p>
|
||||
<p>Technically, "splitting into <span class="arithmatex">\(m\)</span>" corresponds to a time complexity of <span class="arithmatex">\(O(\log_m n)\)</span>. Using the logarithm base change formula, we can equate different logarithmic complexities:</p>
|
||||
<div class="arithmatex">\[
|
||||
O(\log_m n) = O(\log_k n / \log_k m) = O(\log_k n)
|
||||
\]</div>
|
||||
<p>That is, the base <span class="arithmatex">\(m\)</span> can be converted without affecting the complexity. Therefore we usually omit the base <span class="arithmatex">\(m\)</span> and write the logarithmic order directly as <span class="arithmatex">\(O(\log n)\)</span>.</p>
|
||||
<p>This means the base <span class="arithmatex">\(m\)</span> can be changed without affecting the complexity. Therefore, we often omit the base <span class="arithmatex">\(m\)</span> and simply denote logarithmic order as <span class="arithmatex">\(O(\log n)\)</span>.</p>
|
||||
</div>
|
||||
<h3 id="2-linear-logarithmic-order-on-log-n">2. Linear Logarithmic Order <span class="arithmatex">\(O(N \Log N)\)</span><a class="headerlink" href="#2-linear-logarithmic-order-on-log-n" title="Permanent link">¶</a></h3>
|
||||
<p>The linear logarithmic order is often found in nested loops, and the time complexity of the two levels of loops is <span class="arithmatex">\(O(\log n)\)</span> and <span class="arithmatex">\(O(n)\)</span> respectively. The related code is as follows:</p>
|
||||
<h3 id="6-linear-logarithmic-order-on-log-n">6. Linear-Logarithmic Order <span class="arithmatex">\(O(n \log n)\)</span><a class="headerlink" href="#6-linear-logarithmic-order-on-log-n" title="Permanent link">¶</a></h3>
|
||||
<p>Linear-logarithmic order often appears in nested loops, with the complexities of the two loops being <span class="arithmatex">\(O(\log n)\)</span> and <span class="arithmatex">\(O(n)\)</span> respectively. The related code is as follows:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="14:12"><input checked="checked" id="__tabbed_14_1" name="__tabbed_14" type="radio" /><input id="__tabbed_14_2" name="__tabbed_14" type="radio" /><input id="__tabbed_14_3" name="__tabbed_14" type="radio" /><input id="__tabbed_14_4" name="__tabbed_14" type="radio" /><input id="__tabbed_14_5" name="__tabbed_14" type="radio" /><input id="__tabbed_14_6" name="__tabbed_14" type="radio" /><input id="__tabbed_14_7" name="__tabbed_14" type="radio" /><input id="__tabbed_14_8" name="__tabbed_14" type="radio" /><input id="__tabbed_14_9" name="__tabbed_14" type="radio" /><input id="__tabbed_14_10" name="__tabbed_14" type="radio" /><input id="__tabbed_14_11" name="__tabbed_14" type="radio" /><input id="__tabbed_14_12" name="__tabbed_14" type="radio" /><div class="tabbed-labels"><label for="__tabbed_14_1">Python</label><label for="__tabbed_14_2">C++</label><label for="__tabbed_14_3">Java</label><label for="__tabbed_14_4">C#</label><label for="__tabbed_14_5">Go</label><label for="__tabbed_14_6">Swift</label><label for="__tabbed_14_7">JS</label><label for="__tabbed_14_8">TS</label><label for="__tabbed_14_9">Dart</label><label for="__tabbed_14_10">Rust</label><label for="__tabbed_14_11">C</label><label for="__tabbed_14_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -3590,17 +3576,17 @@ O(\log_m n) = O(\log_k n / \log_k m) = O(\log_k n)
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>The Figure 2-13 shows how the linear logarithmic order is generated. The total number of operations at each level of the binary tree is <span class="arithmatex">\(n\)</span> , and the tree has a total of <span class="arithmatex">\(\log_2 n + 1\)</span> levels, resulting in a time complexity of <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="Time complexity of linear logarithmic order" class="animation-figure" src="../time_complexity.assets/time_complexity_logarithmic_linear.png" /></a></p>
|
||||
<p align="center"> Figure 2-13 Time complexity of linear logarithmic order </p>
|
||||
<p>The image below demonstrates how linear-logarithmic order is generated. Each level of a binary tree has <span class="arithmatex">\(n\)</span> operations, and the tree has <span class="arithmatex">\(\log_2 n + 1\)</span> levels, resulting in a time complexity of <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="Linear-Logarithmic Order Time Complexity" class="animation-figure" src="../time_complexity.assets/time_complexity_logarithmic_linear.png" /></a></p>
|
||||
<p align="center"> Figure 2-13 Linear-Logarithmic Order Time Complexity </p>
|
||||
|
||||
<p>Mainstream sorting algorithms typically have a time complexity of <span class="arithmatex">\(O(n \log n)\)</span> , such as quick sort, merge sort, heap sort, etc.</p>
|
||||
<h3 id="3-the-factorial-order-on">3. The Factorial Order <span class="arithmatex">\(O(N!)\)</span><a class="headerlink" href="#3-the-factorial-order-on" title="Permanent link">¶</a></h3>
|
||||
<p>The factorial order corresponds to the mathematical "permutations problem". Given <span class="arithmatex">\(n\)</span> elements that do not repeat each other, find all possible permutations of them, the number of permutations being:</p>
|
||||
<p>Mainstream sorting algorithms typically have a time complexity of <span class="arithmatex">\(O(n \log n)\)</span>, such as quicksort, mergesort, and heapsort.</p>
|
||||
<h3 id="7-factorial-order-on">7. Factorial Order <span class="arithmatex">\(O(n!)\)</span><a class="headerlink" href="#7-factorial-order-on" title="Permanent link">¶</a></h3>
|
||||
<p>Factorial order corresponds to the mathematical problem of "full permutation." Given <span class="arithmatex">\(n\)</span> distinct elements, the total number of possible permutations is:</p>
|
||||
<div class="arithmatex">\[
|
||||
n! = n \times (n - 1) \times (n - 2) \times \dots \times 2 \times 1
|
||||
\]</div>
|
||||
<p>Factorials are usually implemented using recursion. As shown in the Figure 2-14 and in the code below, the first level splits <span class="arithmatex">\(n\)</span>, the second level splits <span class="arithmatex">\(n - 1\)</span>, and so on, until the splitting stops at the <span class="arithmatex">\(n\)</span>th level:</p>
|
||||
<p>Factorials are typically implemented using recursion. As shown in the image and code below, the first level splits into <span class="arithmatex">\(n\)</span> branches, the second level into <span class="arithmatex">\(n - 1\)</span> branches, and so on, stopping after the <span class="arithmatex">\(n\)</span>th level:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="15:12"><input checked="checked" id="__tabbed_15_1" name="__tabbed_15" type="radio" /><input id="__tabbed_15_2" name="__tabbed_15" type="radio" /><input id="__tabbed_15_3" name="__tabbed_15" type="radio" /><input id="__tabbed_15_4" name="__tabbed_15" type="radio" /><input id="__tabbed_15_5" name="__tabbed_15" type="radio" /><input id="__tabbed_15_6" name="__tabbed_15" type="radio" /><input id="__tabbed_15_7" name="__tabbed_15" type="radio" /><input id="__tabbed_15_8" name="__tabbed_15" type="radio" /><input id="__tabbed_15_9" name="__tabbed_15" type="radio" /><input id="__tabbed_15_10" name="__tabbed_15" type="radio" /><input id="__tabbed_15_11" name="__tabbed_15" type="radio" /><input id="__tabbed_15_12" name="__tabbed_15" type="radio" /><div class="tabbed-labels"><label for="__tabbed_15_1">Python</label><label for="__tabbed_15_2">C++</label><label for="__tabbed_15_3">Java</label><label for="__tabbed_15_4">C#</label><label for="__tabbed_15_5">Go</label><label for="__tabbed_15_6">Swift</label><label for="__tabbed_15_7">JS</label><label for="__tabbed_15_8">TS</label><label for="__tabbed_15_9">Dart</label><label for="__tabbed_15_10">Rust</label><label for="__tabbed_15_11">C</label><label for="__tabbed_15_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -3769,17 +3755,17 @@ 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="Time complexity of the factorial order" class="animation-figure" src="../time_complexity.assets/time_complexity_factorial.png" /></a></p>
|
||||
<p align="center"> Figure 2-14 Time complexity of the factorial order </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="Factorial Order Time Complexity" class="animation-figure" src="../time_complexity.assets/time_complexity_factorial.png" /></a></p>
|
||||
<p align="center"> Figure 2-14 Factorial Order Time Complexity </p>
|
||||
|
||||
<p>Note that since there is always <span class="arithmatex">\(n! > 2^n\)</span> when <span class="arithmatex">\(n \geq 4\)</span>, the factorial order grows faster than the exponential order, and is also unacceptable when <span class="arithmatex">\(n\)</span> is large.</p>
|
||||
<h2 id="236-worst-best-average-time-complexity">2.3.6 Worst, Best, Average Time Complexity<a class="headerlink" href="#236-worst-best-average-time-complexity" title="Permanent link">¶</a></h2>
|
||||
<p><strong>The time efficiency of algorithms is often not fixed, but is related to the distribution of the input data</strong>. Suppose an array <code>nums</code> of length <span class="arithmatex">\(n\)</span> is input, where <code>nums</code> consists of numbers from <span class="arithmatex">\(1\)</span> to <span class="arithmatex">\(n\)</span>, each of which occurs only once; however, the order of the elements is randomly upset, and the goal of the task is to return the index of element <span class="arithmatex">\(1\)</span>. We can draw the following conclusion.</p>
|
||||
<p>Note that factorial order grows even faster than exponential order; it's unacceptable for larger <span class="arithmatex">\(n\)</span> values.</p>
|
||||
<h2 id="235-worst-best-and-average-time-complexities">2.3.5 Worst, Best, and Average Time Complexities<a class="headerlink" href="#235-worst-best-and-average-time-complexities" title="Permanent link">¶</a></h2>
|
||||
<p><strong>The time efficiency of an algorithm is often not fixed but depends on the distribution of the input data</strong>. Assume we have an array <code>nums</code> of length <span class="arithmatex">\(n\)</span>, consisting of numbers from <span class="arithmatex">\(1\)</span> to <span class="arithmatex">\(n\)</span>, each appearing only once, but in a randomly shuffled order. The task is to return the index of the element <span class="arithmatex">\(1\)</span>. We can draw the following conclusions:</p>
|
||||
<ul>
|
||||
<li>When <code>nums = [? , ? , ... , 1]</code> , i.e., when the end element is <span class="arithmatex">\(1\)</span>, a complete traversal of the array is required, <strong>to reach the worst time complexity <span class="arithmatex">\(O(n)\)</span></strong> .</li>
|
||||
<li>When <code>nums = [1, ? , ? , ...]</code> , i.e., when the first element is <span class="arithmatex">\(1\)</span> , there is no need to continue traversing the array no matter how long it is, <strong>reaching the optimal time complexity <span class="arithmatex">\(\Omega(1)\)</span></strong> .</li>
|
||||
<li>When <code>nums = [?, ?, ..., 1]</code>, that is, when the last element is <span class="arithmatex">\(1\)</span>, it requires a complete traversal of the array, <strong>achieving the worst-case time complexity of <span class="arithmatex">\(O(n)\)</span></strong>.</li>
|
||||
<li>When <code>nums = [1, ?, ?, ...]</code>, that is, when the first element is <span class="arithmatex">\(1\)</span>, no matter the length of the array, no further traversal is needed, <strong>achieving the best-case time complexity of <span class="arithmatex">\(\Omega(1)\)</span></strong>.</li>
|
||||
</ul>
|
||||
<p>The "worst time complexity" corresponds to the asymptotic upper bound of the function and is denoted by the large <span class="arithmatex">\(O\)</span> notation. Correspondingly, the "optimal time complexity" corresponds to the asymptotic lower bound of the function and is denoted in <span class="arithmatex">\(\Omega\)</span> notation:</p>
|
||||
<p>The "worst-case time complexity" corresponds to the asymptotic upper bound, denoted by the big <span class="arithmatex">\(O\)</span> notation. Correspondingly, the "best-case time complexity" corresponds to the asymptotic lower bound, denoted by <span class="arithmatex">\(\Omega\)</span>:</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="16:12"><input checked="checked" id="__tabbed_16_1" name="__tabbed_16" type="radio" /><input id="__tabbed_16_2" name="__tabbed_16" type="radio" /><input id="__tabbed_16_3" name="__tabbed_16" type="radio" /><input id="__tabbed_16_4" name="__tabbed_16" type="radio" /><input id="__tabbed_16_5" name="__tabbed_16" type="radio" /><input id="__tabbed_16_6" name="__tabbed_16" type="radio" /><input id="__tabbed_16_7" name="__tabbed_16" type="radio" /><input id="__tabbed_16_8" name="__tabbed_16" type="radio" /><input id="__tabbed_16_9" name="__tabbed_16" type="radio" /><input id="__tabbed_16_10" name="__tabbed_16" type="radio" /><input id="__tabbed_16_11" name="__tabbed_16" type="radio" /><input id="__tabbed_16_12" name="__tabbed_16" type="radio" /><div class="tabbed-labels"><label for="__tabbed_16_1">Python</label><label for="__tabbed_16_2">C++</label><label for="__tabbed_16_3">Java</label><label for="__tabbed_16_4">C#</label><label for="__tabbed_16_5">Go</label><label for="__tabbed_16_6">Swift</label><label for="__tabbed_16_7">JS</label><label for="__tabbed_16_8">TS</label><label for="__tabbed_16_9">Dart</label><label for="__tabbed_16_10">Rust</label><label for="__tabbed_16_11">C</label><label for="__tabbed_16_12">Zig</label></div>
|
||||
<div class="tabbed-content">
|
||||
<div class="tabbed-block">
|
||||
|
@ -4107,13 +4093,13 @@ n! = n \times (n - 1) \times (n - 2) \times \dots \times 2 \times 1
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>It is worth stating that we rarely use the optimal time complexity in practice because it is usually only attainable with a small probability and may be somewhat misleading. <strong>whereas the worst time complexity is more practical because it gives a safe value for efficiency and allows us to use the algorithm with confidence</strong>.</p>
|
||||
<p>From the above examples, it can be seen that the worst or best time complexity only occurs in "special data distributions", and the probability of these cases may be very small, which does not truly reflect the efficiency of the algorithm. In contrast, <strong>the average time complexity of can reflect the efficiency of the algorithm under random input data</strong>, which is denoted by the <span class="arithmatex">\(\Theta\)</span> notation.</p>
|
||||
<p>For some algorithms, we can simply derive the average case under a random data distribution. For example, in the above example, since the input array is scrambled, the probability of an element <span class="arithmatex">\(1\)</span> appearing at any index is equal, so the average number of loops of the algorithm is half of the length of the array <span class="arithmatex">\(n / 2\)</span> , and the average time complexity is <span class="arithmatex">\(\Theta(n / 2) = \Theta(n)\)</span> .</p>
|
||||
<p>However, for more complex algorithms, calculating the average time complexity is often difficult because it is hard to analyze the overall mathematical expectation given the data distribution. In this case, we usually use the worst time complexity as a criterion for the efficiency of the algorithm.</p>
|
||||
<p>It's important to note that the best-case time complexity is rarely used in practice, as it is usually only achievable under very low probabilities and might be misleading. <strong>The worst-case time complexity is more practical as it provides a safety value for efficiency</strong>, allowing us to confidently use the algorithm.</p>
|
||||
<p>From the above example, it's clear that both the worst-case and best-case time complexities only occur under "special data distributions," which may have a small probability of occurrence and may not accurately reflect the algorithm's run efficiency. In contrast, <strong>the average time complexity can reflect the algorithm's efficiency under random input data</strong>, denoted by the <span class="arithmatex">\(\Theta\)</span> notation.</p>
|
||||
<p>For some algorithms, we can simply estimate the average case under a random data distribution. For example, in the aforementioned example, since the input array is shuffled, the probability of element <span class="arithmatex">\(1\)</span> appearing at any index is equal. Therefore, the average number of loops for the algorithm is half the length of the array <span class="arithmatex">\(n / 2\)</span>, giving an average time complexity of <span class="arithmatex">\(\Theta(n / 2) = \Theta(n)\)</span>.</p>
|
||||
<p>However, calculating the average time complexity for more complex algorithms can be quite difficult, as it's challenging to analyze the overall mathematical expectation under the data distribution. In such cases, we usually use the worst-case time complexity as the standard for judging the efficiency of the algorithm.</p>
|
||||
<div class="admonition question">
|
||||
<p class="admonition-title">Why do you rarely see the <span class="arithmatex">\(\Theta\)</span> symbol?</p>
|
||||
<p>Perhaps because the <span class="arithmatex">\(O\)</span> symbol is so catchy, we often use it to denote average time complexity. However, this practice is not standardized in the strict sense. In this book and other sources, if you encounter a statement like "average time complexity <span class="arithmatex">\(O(n)\)</span>", please understand it as <span class="arithmatex">\(\Theta(n)\)</span>.</p>
|
||||
<p class="admonition-title">Why is the <span class="arithmatex">\(\Theta\)</span> symbol rarely seen?</p>
|
||||
<p>Possibly because the <span class="arithmatex">\(O\)</span> notation is more commonly spoken, it is often used to represent the average time complexity. However, strictly speaking, this practice is not accurate. In this book and other materials, if you encounter statements like "average time complexity <span class="arithmatex">\(O(n)\)</span>", please understand it directly as <span class="arithmatex">\(\Theta(n)\)</span>.</p>
|
||||
</div>
|
||||
|
||||
<!-- Source file information -->
|
||||
|
|
|
@ -789,8 +789,8 @@
|
|||
</div>
|
||||
<div class="admonition abstract">
|
||||
<p class="admonition-title">Abstract</p>
|
||||
<p>Data structures are like a solid and varied framework.</p>
|
||||
<p>It provides a blueprint for the orderly organization of data upon which algorithms can come alive.</p>
|
||||
<p>Data structures resemble a stable and diverse framework.</p>
|
||||
<p>They serve as a blueprint for organizing data orderly, enabling algorithms to come to life upon this foundation.</p>
|
||||
</div>
|
||||
|
||||
<!-- Source file information -->
|
||||
|
|
|
@ -799,47 +799,47 @@
|
|||
|
||||
|
||||
<!-- Page content -->
|
||||
<h1 id="11-algorithms-are-everywhere">1.1 Algorithms Are Everywhere<a class="headerlink" href="#11-algorithms-are-everywhere" title="Permanent link">¶</a></h1>
|
||||
<p>When we hear the word "algorithm", we naturally think of mathematics. However, many algorithms do not involve complex mathematics but rely more on basic logic, which is ubiquitous in our daily lives.</p>
|
||||
<p>Before we formally discuss algorithms, an interesting fact is worth sharing: <strong>you have already learned many algorithms unconsciously and have become accustomed to applying them in your daily life</strong>. Below, I will give a few specific examples to prove this point.</p>
|
||||
<p><strong>Example 1: Looking Up a Dictionary</strong>. In a standard dictionary, each word corresponds to a phonetic transcription and the dictionary is organized alphabetically based on these transcriptions. Let's say we're looking for a word that begins with the letter <span class="arithmatex">\(r\)</span>. This is typically done in the following way:</p>
|
||||
<h1 id="11-algorithms-are-everywhere">1.1 Algorithms are Everywhere<a class="headerlink" href="#11-algorithms-are-everywhere" title="Permanent link">¶</a></h1>
|
||||
<p>When we hear the word "algorithm," we naturally think of mathematics. However, many algorithms do not involve complex mathematics but rely more on basic logic, which can be seen everywhere in our daily lives.</p>
|
||||
<p>Before formally discussing algorithms, there's an interesting fact worth sharing: <strong>you have already unconsciously learned many algorithms and have become accustomed to applying them in your daily life</strong>. Here, I will give a few specific examples to prove this point.</p>
|
||||
<p><strong>Example 1: Looking Up a Dictionary</strong>. In an English dictionary, words are listed alphabetically. Suppose we're searching for a word that starts with the letter <span class="arithmatex">\(r\)</span>. This is typically done in the following way:</p>
|
||||
<ol>
|
||||
<li>Open the dictionary around its midpoint and note the first letter on that page, assuming it to be <span class="arithmatex">\(m\)</span>.</li>
|
||||
<li>Given the sequence of words following the initial letter <span class="arithmatex">\(m\)</span>, estimate where words starting with the letter <span class="arithmatex">\(r\)</span> might be located within the alphabetical order.</li>
|
||||
<li>Iterate steps <code>1.</code> and <code>2.</code> until you find the page where the word begins with the letter <span class="arithmatex">\(r\)</span>.</li>
|
||||
<li>Open the dictionary to about halfway and check the first letter on the page, let's say the letter is <span class="arithmatex">\(m\)</span>.</li>
|
||||
<li>Since <span class="arithmatex">\(r\)</span> comes after <span class="arithmatex">\(m\)</span> in the alphabet, we can ignore the first half of the dictionary and focus on the latter half.</li>
|
||||
<li>Repeat steps <code>1.</code> and <code>2.</code> until you find the page where the word starts with <span class="arithmatex">\(r\)</span>.</li>
|
||||
</ol>
|
||||
<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="Dictionary search step" class="animation-figure" 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="Process of Looking Up a Dictionary" 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" class="animation-figure" 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 in Dictionary Step 2" 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" class="animation-figure" 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 in Dictionary Step 3" 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" class="animation-figure" 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 in Dictionary Step 4" 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" class="animation-figure" 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 in Dictionary Step 5" class="animation-figure" src="../algorithms_are_everywhere.assets/binary_search_dictionary_step5.png" /></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p align="center"> Figure 1-1 Dictionary search step </p>
|
||||
<p align="center"> Figure 1-1 Process of Looking Up a Dictionary </p>
|
||||
|
||||
<p>The skill of looking up a dictionary, essential for elementary school students, is actually the renowned binary search algorithm. Through the lens of data structures, we can view the dictionary as a sorted "array"; while from an algorithmic perspective, the series of operations in looking up a dictionary can be seen as "binary search".</p>
|
||||
<p><strong>Example 2: Organizing Playing Cards</strong>. When playing cards, we need to arrange the cards in ascending order each game, as shown in the following process.</p>
|
||||
<p>This essential skill for elementary students, looking up a dictionary, is actually the famous "Binary Search" algorithm. From a data structure perspective, we can consider the dictionary as a sorted "array"; from an algorithmic perspective, the series of actions taken to look up a word in the dictionary can be viewed as "Binary Search."</p>
|
||||
<p><strong>Example 2: Organizing Playing Cards</strong>. When playing cards, we need to arrange the cards in our hand in ascending order, as shown in the following process.</p>
|
||||
<ol>
|
||||
<li>Divide the playing cards into "ordered" and "unordered" parts, assuming initially that the leftmost card is already ordered.</li>
|
||||
<li>Take out a card from the unordered part and insert it into the correct position in the ordered part; once completed, the leftmost two cards will be in an ordered sequence.</li>
|
||||
<li>Continue the loop described in step <code>2.</code>, each iteration involving insertion of one card from the unordered segment into the ordered portion, until all cards are appropriately ordered.</li>
|
||||
<li>Divide the playing cards into "ordered" and "unordered" sections, assuming initially the leftmost card is already in order.</li>
|
||||
<li>Take out a card from the unordered section and insert it into the correct position in the ordered section; after this, the leftmost two cards are in order.</li>
|
||||
<li>Continue to repeat step <code>2.</code> until all cards are in order.</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="Playing cards sorting process" class="animation-figure" src="../algorithms_are_everywhere.assets/playing_cards_sorting.png" /></a></p>
|
||||
<p align="center"> Figure 1-2 Playing cards sorting process </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="Playing Cards Sorting Process" class="animation-figure" src="../algorithms_are_everywhere.assets/playing_cards_sorting.png" /></a></p>
|
||||
<p align="center"> Figure 1-2 Playing Cards Sorting Process </p>
|
||||
|
||||
<p>The above method of organizing playing cards is essentially the "insertion sort" algorithm, which is very efficient for small datasets. Many programming languages' sorting library functions include insertion sort.</p>
|
||||
<p>The above method of organizing playing cards is essentially the "Insertion Sort" algorithm, which is very efficient for small datasets. Many programming languages' sorting functions include the insertion sort.</p>
|
||||
<p><strong>Example 3: Making Change</strong>. Suppose we buy goods worth <span class="arithmatex">\(69\)</span> yuan at a supermarket and give the cashier <span class="arithmatex">\(100\)</span> yuan, then the cashier needs to give us <span class="arithmatex">\(31\)</span> yuan in change. They would naturally complete the thought process as shown below.</p>
|
||||
<ol>
|
||||
<li>The options are currencies smaller than <span class="arithmatex">\(31\)</span>, including <span class="arithmatex">\(1\)</span>, <span class="arithmatex">\(5\)</span>, <span class="arithmatex">\(10\)</span>, and <span class="arithmatex">\(20\)</span>.</li>
|
||||
|
@ -851,8 +851,8 @@
|
|||
<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="Change making process" class="animation-figure" src="../algorithms_are_everywhere.assets/greedy_change.png" /></a></p>
|
||||
<p align="center"> Figure 1-3 Change making process </p>
|
||||
|
||||
<p>In the aforementioned steps, at each stage, we make the optimal choice (utilizing the highest denomination possible), ultimately deriving at a feasible change-making approach. From the perspective of data structures and algorithms, this approach is essentially a "greedy" algorithm.</p>
|
||||
<p>From preparing a dish to traversing interstellar realms, virtually every problem-solving endeavor relies on algorithms. The emergence of computers enables us to store data structures in memory and write code to call CPUs and GPUs to execute algorithms. Consequently, we can transfer real-life predicaments to computers, efficiently addressing a myriad of complex issues.</p>
|
||||
<p>In the above steps, we make the best choice at each step (using the largest denomination possible), ultimately resulting in a feasible change-making plan. From the perspective of data structures and algorithms, this method is essentially a "Greedy" algorithm.</p>
|
||||
<p>From cooking a meal to interstellar travel, almost all problem-solving involves algorithms. The advent of computers allows us to store data structures in memory and write code to call the CPU and GPU to execute algorithms. In this way, we can transfer real-life problems to computers, solving various complex issues more efficiently.</p>
|
||||
<div class="admonition tip">
|
||||
<p class="admonition-title">Tip</p>
|
||||
<p>If concepts such as data structures, algorithms, arrays, and binary search still seem somewhat obsecure, I encourage you to continue reading. This book will gently guide you into the realm of understanding data structures and algorithms.</p>
|
||||
|
|
|
@ -912,7 +912,7 @@
|
|||
<li>Graphs, compared to linked lists, provide richer logical information but require more memory space.</li>
|
||||
</ul>
|
||||
<h2 id="123-relationship-between-data-structures-and-algorithms">1.2.3 Relationship Between Data Structures and Algorithms<a class="headerlink" href="#123-relationship-between-data-structures-and-algorithms" title="Permanent link">¶</a></h2>
|
||||
<p>As shown in the diagram below, data structures and algorithms are highly related and closely integrated, specifically in the following three aspects:</p>
|
||||
<p>As shown in the Figure 1-4 , data structures and algorithms are highly related and closely integrated, specifically in the following three aspects:</p>
|
||||
<ul>
|
||||
<li>Data structures are the foundation of algorithms. They provide structured data storage and methods for manipulating data for algorithms.</li>
|
||||
<li>Algorithms are the stage where data structures come into play. The data structure alone only stores data information; it is through the application of algorithms that specific problems can be solved.</li>
|
||||
|
|
|
@ -91,7 +91,7 @@
|
|||
<div data-md-component="skip">
|
||||
|
||||
|
||||
<a href="#01-the-book" class="md-skip">
|
||||
<a href="#01-about-this-book" class="md-skip">
|
||||
Skip to content
|
||||
</a>
|
||||
|
||||
|
@ -410,9 +410,9 @@
|
|||
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#011-target-readers" class="md-nav__link">
|
||||
<a href="#011-target-audience" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
0.1.1 Target Readers
|
||||
0.1.1 Target Audience
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -829,9 +829,9 @@
|
|||
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#011-target-readers" class="md-nav__link">
|
||||
<a href="#011-target-audience" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
0.1.1 Target Readers
|
||||
0.1.1 Target Audience
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
@ -891,43 +891,44 @@
|
|||
|
||||
|
||||
<!-- Page content -->
|
||||
<h1 id="01-the-book">0.1 The Book<a class="headerlink" href="#01-the-book" title="Permanent link">¶</a></h1>
|
||||
<p>The aim of this project is to create an open source, free, novice-friendly introductory tutorial on data structures and algorithms.</p>
|
||||
<h1 id="01-about-this-book">0.1 About This Book<a class="headerlink" href="#01-about-this-book" title="Permanent link">¶</a></h1>
|
||||
<p>This open-source project aims to create a free, and beginner-friendly crash course on data structures and algorithms.</p>
|
||||
<ul>
|
||||
<li>Animated graphs are used throughout the book to structure the knowledge of data structures and algorithms in a way that is clear and easy to understand with a smooth learning curve.</li>
|
||||
<li>The source code of the algorithms can be run with a single click, supporting Java, C++, Python, Go, JS, TS, C#, Swift, Rust, Dart, Zig and other languages.</li>
|
||||
<li>Readers are encouraged to help each other and make progress in the chapter discussion forums, and questions and comments can usually be answered within two days.</li>
|
||||
<li>Using animated illustrations, it delivers structured insights into data structures and algorithmic concepts, ensuring comprehensibility and a smooth learning curve.</li>
|
||||
<li>Run code with just one click, supporting Java, C++, Python, Go, JS, TS, C#, Swift, Rust, Dart, Zig and other languages.</li>
|
||||
<li>Readers are encouraged to engage with each other in the discussion area for each section, questions and comments are usually answered within two days.</li>
|
||||
</ul>
|
||||
<h2 id="011-target-readers">0.1.1 Target Readers<a class="headerlink" href="#011-target-readers" title="Permanent link">¶</a></h2>
|
||||
<p>If you are a beginner to algorithms, have never touched an algorithm before, or already have some experience brushing up on data structures and algorithms, and have a vague understanding of data structures and algorithms, repeatedly jumping sideways between what you can and can't do, then this book is just for you!</p>
|
||||
<p>If you have already accumulated a certain amount of questions and are familiar with most of the question types, then this book can help you review and organize the algorithm knowledge system, and the repository source code can be used as a "brushing tool library" or "algorithm dictionary".</p>
|
||||
<p>If you are an algorithm expert, we look forward to receiving your valuable suggestions or <a href="https://www.hello-algo.com/chapter_appendix/contribution/">participate in the creation together</a>.</p>
|
||||
<h2 id="011-target-audience">0.1.1 Target Audience<a class="headerlink" href="#011-target-audience" title="Permanent link">¶</a></h2>
|
||||
<p>If you are new to algorithms with limited exposure, or you have accumulated some experience in algorithms, but you only have a vague understanding of data structures and algorithms, and you are constantly jumping between "yep" and "hmm", then this book is for you!</p>
|
||||
<p>If you have already accumulated a certain amount of problem-solving experience, and are familiar with most types of problems, then this book can help you review and organize your algorithm knowledge system. The repository's source code can be used as a "problem-solving toolkit" or an "algorithm cheat sheet".</p>
|
||||
<p>If you are an algorithm expert, we look forward to receiving your valuable suggestions, or <a href="https://www.hello-algo.com/chapter_appendix/contribution/">join us and collaborate</a>.</p>
|
||||
<div class="admonition success">
|
||||
<p class="admonition-title">precondition</p>
|
||||
<p>You will need to have at least a basic knowledge of programming in any language and be able to read and write simple code.</p>
|
||||
<p class="admonition-title">Prerequisites</p>
|
||||
<p>You should know how to write and read simple code in at least one programming language.</p>
|
||||
</div>
|
||||
<h2 id="012-content-structure">0.1.2 Content Structure<a class="headerlink" href="#012-content-structure" title="Permanent link">¶</a></h2>
|
||||
<p>The main contents of the book are shown in the Figure 0-1 .</p>
|
||||
<p>The main content of the book is shown in the following figure.</p>
|
||||
<ul>
|
||||
<li><strong>Complexity Analysis</strong>: dimensions and methods of evaluation of data structures and algorithms. Methods of deriving time complexity, space complexity, common types, examples, etc.</li>
|
||||
<li><strong>Data Structures</strong>: basic data types, classification methods of data structures. Definition, advantages and disadvantages, common operations, common types, typical applications, implementation methods of data structures such as arrays, linked lists, stacks, queues, hash tables, trees, heaps, graphs, etc.</li>
|
||||
<li><strong>Algorithms</strong>: definitions, advantages and disadvantages, efficiency, application scenarios, solution steps, sample topics of search, sorting algorithms, divide and conquer, backtracking algorithms, dynamic programming, greedy algorithms, and more.</li>
|
||||
<li><strong>Complexity Analysis</strong>: explores aspects and methods for evaluating data structures and algorithms. Covers methods of deriving time complexity and space complexity, along with common types and examples.</li>
|
||||
<li><strong>Data Structures</strong>: focuses on fundamental data types, classification methods, definitions, pros and cons, common operations, types, applications, and implementation methods of data structures such as array, linked list, stack, queue, hash table, tree, heap, graph, etc.</li>
|
||||
<li><strong>Algorithms</strong>: defines algorithms, discusses their pros and cons, efficiency, application scenarios, problem-solving steps, and includes sample questions for various algorithms such as search, sorting, divide and conquer, backtracking, dynamic programming, greedy algorithms, and more.</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 Algo content structure" class="animation-figure" src="../about_the_book.assets/hello_algo_mindmap.jpg" /></a></p>
|
||||
<p align="center"> Figure 0-1 Hello Algo content structure </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="Main Content of the Book" class="animation-figure" src="../about_the_book.assets/hello_algo_mindmap.jpg" /></a></p>
|
||||
<p align="center"> Figure 0-1 Main Content of the Book </p>
|
||||
|
||||
<h2 id="013-acknowledgements">0.1.3 Acknowledgements<a class="headerlink" href="#013-acknowledgements" title="Permanent link">¶</a></h2>
|
||||
<p>During the creation of this book, I received help from many people, including but not limited to:</p>
|
||||
<p>Throughout the creation of this book, numerous individuals provided invaluable assistance, including but not limited to:</p>
|
||||
<ul>
|
||||
<li>Thank you to my mentor at the company, Dr. Shih Lee, for encouraging me to "get moving" during one of our conversations, which strengthened my resolve to write this book.</li>
|
||||
<li>I would like to thank my girlfriend Bubbles for being the first reader of this book, and for making many valuable suggestions from the perspective of an algorithm whiz, making this book more suitable for newbies.</li>
|
||||
<li>Thanks to Tengbao, Qibao, and Feibao for coming up with a creative name for this book that evokes fond memories of writing the first line of code "Hello World!".</li>
|
||||
<li>Thanks to Sutong for designing the beautiful cover and logo for this book and patiently revising it many times under my OCD.</li>
|
||||
<li>Thanks to @squidfunk for writing layout suggestions and for developing the open source documentation theme <a href="https://github.com/squidfunk/mkdocs-material/tree/master">Material-for-MkDocs</a>.</li>
|
||||
<li>Thanks to my mentor at the company, Dr. Xi Li, who encouraged me in a conversation to "get moving fast," which solidified my determination to write this book;</li>
|
||||
<li>Thanks to my girlfriend Paopao, as the first reader of this book, for offering many valuable suggestions from the perspective of a beginner in algorithms, making this book more suitable for newbies;</li>
|
||||
<li>Thanks to Tengbao, Qibao, and Feibao for coming up with a creative name for this book, evoking everyone's fond memories of writing their first line of code "Hello World!";</li>
|
||||
<li>Thanks to Xiaoquan for providing professional help in intellectual property, which has played a significant role in the development of this open-source book;</li>
|
||||
<li>Thanks to Sutong for designing a beautiful cover and logo for this book, and for patiently making multiple revisions under my insistence;</li>
|
||||
<li>Thanks to @squidfunk for providing writing and typesetting suggestions, as well as his developed open-source documentation theme <a href="https://github.com/squidfunk/mkdocs-material/tree/master">Material-for-MkDocs</a>.</li>
|
||||
</ul>
|
||||
<p>During the writing process, I read many textbooks and articles on data structures and algorithms. These works provide excellent models for this book and ensure the accuracy and quality of its contents. I would like to thank all my teachers and predecessors for their outstanding contributions!</p>
|
||||
<p>This book promotes a hands-on approach to learning, and in this respect is heavily inspired by <a href="https://github.com/d2l-ai/d2l-zh">"Dive into Deep Learning"</a>. I highly recommend this excellent book to you.</p>
|
||||
<p><strong>A heartfelt thank you to my parents, it is your constant support and encouragement that gives me the opportunity to do this fun-filled thing</strong>.</p>
|
||||
<p>Throughout the writing journey, I delved into numerous textbooks and articles on data structures and algorithms. These works served as exemplary models, ensuring the accuracy and quality of this book's content. I extend my gratitude to all who preceded me for their invaluable contributions!</p>
|
||||
<p>This book advocates a combination of hands-on and minds-on learning, inspired in this regard by <a href="https://github.com/d2l-ai/d2l-zh">"Dive into Deep Learning"</a>. I highly recommend this excellent book to all readers.</p>
|
||||
<p><strong>Heartfelt thanks to my parents, whose ongoing support and encouragement have allowed me to do this interesting work</strong>.</p>
|
||||
|
||||
<!-- Source file information -->
|
||||
|
||||
|
|
|
@ -811,7 +811,7 @@
|
|||
<div class="admonition abstract">
|
||||
<p class="admonition-title">Abstract</p>
|
||||
<p>Algorithms are like a beautiful symphony, with each line of code flowing like a rhythm.</p>
|
||||
<p>May this book ring softly in your head, leaving a unique and profound melody.</p>
|
||||
<p>May this book ring softly in your mind, leaving a unique and profound melody.</p>
|
||||
</div>
|
||||
<h2 id="_1">本章内容<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
|
||||
<ul>
|
||||
|
|
|
@ -804,9 +804,9 @@
|
|||
<li>The main audience of this book is beginners in algorithm. If you already have some basic knowledge, this book can help you systematically review your algorithm knowledge, and the source code in this book can also be used as a "Coding Toolkit".</li>
|
||||
<li>The book consists of three main sections, Complexity Analysis, Data Structures, and Algorithms, covering most of the topics in the field.</li>
|
||||
<li>For newcomers to algorithms, it is crucial to read an introductory book in the beginning stages to avoid many detours or common pitfalls.</li>
|
||||
<li>Animations and graphs within the book are usually used to introduce key points and difficult knowledge. These should be given more attention when reading the book.</li>
|
||||
<li>Animations and figures within the book are usually used to introduce key points and difficult knowledge. These should be given more attention when reading the book.</li>
|
||||
<li>Practice is the best way to learn programming. It is highly recommended that you run the source code and type in the code yourself.</li>
|
||||
<li>Each chapter in the web version of this book features a discussion forum, and you are welcome to share your questions and insights at any time.</li>
|
||||
<li>Each chapter in the web version of this book features a discussion section, and you are welcome to share your questions and insights at any time.</li>
|
||||
</ul>
|
||||
|
||||
<!-- Source file information -->
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -2,87 +2,87 @@
|
|||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/en/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/en/chapter_computational_complexity/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/en/chapter_computational_complexity/iteration_and_recursion/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/en/chapter_computational_complexity/performance_evaluation/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/en/chapter_computational_complexity/space_complexity/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/en/chapter_computational_complexity/summary/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/en/chapter_computational_complexity/time_complexity/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/en/chapter_data_structure/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/en/chapter_data_structure/classification_of_data_structure/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/en/chapter_introduction/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/en/chapter_introduction/algorithms_are_everywhere/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/en/chapter_introduction/summary/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/en/chapter_introduction/what_is_dsa/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/en/chapter_preface/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/en/chapter_preface/about_the_book/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/en/chapter_preface/suggestions/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/en/chapter_preface/summary/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
</urlset>
|
Binary file not shown.
File diff suppressed because one or more lines are too long
208
sitemap.xml
208
sitemap.xml
|
@ -2,522 +2,522 @@
|
|||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_appendix/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_appendix/contribution/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_appendix/installation/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_appendix/terminology/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_array_and_linkedlist/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_array_and_linkedlist/array/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_array_and_linkedlist/linked_list/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_array_and_linkedlist/list/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_array_and_linkedlist/ram_and_cache/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_array_and_linkedlist/summary/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_backtracking/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_backtracking/backtracking_algorithm/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_backtracking/n_queens_problem/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_backtracking/permutations_problem/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_backtracking/subset_sum_problem/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_backtracking/summary/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_computational_complexity/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_computational_complexity/iteration_and_recursion/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_computational_complexity/performance_evaluation/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_computational_complexity/space_complexity/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_computational_complexity/summary/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_computational_complexity/time_complexity/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_data_structure/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_data_structure/basic_data_types/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_data_structure/character_encoding/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_data_structure/classification_of_data_structure/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_data_structure/number_encoding/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_data_structure/summary/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_divide_and_conquer/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_divide_and_conquer/binary_search_recur/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_divide_and_conquer/build_binary_tree_problem/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_divide_and_conquer/divide_and_conquer/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_divide_and_conquer/hanota_problem/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_divide_and_conquer/summary/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_dynamic_programming/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_dynamic_programming/dp_problem_features/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_dynamic_programming/dp_solution_pipeline/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_dynamic_programming/edit_distance_problem/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_dynamic_programming/intro_to_dynamic_programming/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_dynamic_programming/knapsack_problem/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_dynamic_programming/summary/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_dynamic_programming/unbounded_knapsack_problem/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_graph/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_graph/graph/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_graph/graph_operations/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_graph/graph_traversal/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_graph/summary/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_greedy/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_greedy/fractional_knapsack_problem/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_greedy/greedy_algorithm/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_greedy/max_capacity_problem/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_greedy/max_product_cutting_problem/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_greedy/summary/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_hashing/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_hashing/hash_algorithm/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_hashing/hash_collision/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_hashing/hash_map/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_hashing/summary/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_heap/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_heap/build_heap/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_heap/heap/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_heap/summary/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_heap/top_k/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_introduction/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_introduction/algorithms_are_everywhere/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_introduction/summary/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_introduction/what_is_dsa/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_preface/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_preface/about_the_book/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_preface/suggestions/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_preface/summary/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_reference/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_searching/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_searching/binary_search/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_searching/binary_search_edge/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_searching/binary_search_insertion/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_searching/replace_linear_by_hashing/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_searching/searching_algorithm_revisited/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_searching/summary/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/bubble_sort/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/bucket_sort/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/counting_sort/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/heap_sort/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/insertion_sort/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/merge_sort/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/quick_sort/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/radix_sort/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/selection_sort/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/sorting_algorithm/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_sorting/summary/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_stack_and_queue/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_stack_and_queue/deque/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_stack_and_queue/queue/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_stack_and_queue/stack/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_stack_and_queue/summary/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_tree/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_tree/array_representation_of_tree/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_tree/avl_tree/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_tree/binary_search_tree/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_tree/binary_tree/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_tree/binary_tree_traversal/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://www.hello-algo.com/chapter_tree/summary/</loc>
|
||||
<lastmod>2023-12-21</lastmod>
|
||||
<lastmod>2023-12-24</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
</urlset>
|
BIN
sitemap.xml.gz
BIN
sitemap.xml.gz
Binary file not shown.
Loading…
Reference in a new issue