mirror of
https://github.com/CyC2018/Interview-Notebook.git
synced 2026-11-01 11:43:46 +00:00
Update 算法 - 其它.md
调整汉诺塔递归步骤与移动次数的推导说明,补充哈夫曼编码长度对比及解码特性的描述。
This commit is contained in:
+8
-6
@@ -5,23 +5,23 @@
|
||||
|
||||
有三个柱子,分别为 from、buffer、to。需要将 from 上的圆盘全部移动到 to 上,并且要保证小圆盘始终在大圆盘上。
|
||||
|
||||
这是一个经典的递归问题,分为三步求解:
|
||||
这是一个经典的递归问题。如果只有一个圆盘,直接从 from 移到 to;有 n 个圆盘时分为三步:
|
||||
|
||||
① 将 n-1 个圆盘从 from -\> buffer
|
||||
第一步,借助 to,将上面的 n - 1 个圆盘从 from 移到 buffer。
|
||||
|
||||
<div align="center"> <img src="pics/hanoi-step1.png" width="460px"/> </div><br>
|
||||
|
||||
② 将 1 个圆盘从 from -\> to
|
||||
第二步,将最大的圆盘从 from 移到 to。
|
||||
|
||||
<div align="center"> <img src="pics/hanoi-step2.png" width="460px"/> </div><br>
|
||||
|
||||
③ 将 n-1 个圆盘从 buffer -\> to
|
||||
第三步,借助 from,将 n - 1 个圆盘从 buffer 移到 to。
|
||||
|
||||
<div align="center"> <img src="pics/hanoi-step3.png" width="460px"/> </div><br>
|
||||
|
||||
如果只有一个圆盘,那么只需要进行一次移动操作。
|
||||
“借助”的柱子就是递归调用中的 buffer 参数,因此代码中第一步和第三步调用 move() 时交换了参数的顺序。
|
||||
|
||||
从上面的讨论可以知道,a<sub>n</sub> = 2 * a<sub>n-1</sub> + 1,显然 a<sub>n</sub> = 2<sup>n</sup> - 1,n 个圆盘需要移动 2<sup>n</sup> - 1 次。
|
||||
设 n 个圆盘需要移动 a<sub>n</sub> 次,由三个步骤得到 a<sub>n</sub> = 2a<sub>n-1</sub> + 1,a<sub>1</sub> = 1。两边加 1 得到 a<sub>n</sub> + 1 = 2(a<sub>n-1</sub> + 1),因此 a<sub>n</sub> = 2<sup>n</sup> - 1,例如 3 个圆盘需要移动 7 次。
|
||||
|
||||
```java
|
||||
public class Hanoi {
|
||||
@@ -68,6 +68,8 @@ from H1 to H3
|
||||
|
||||
生成编码时,从根节点出发,向左遍历则添加二进制位 0,向右则添加二进制位 1,直到遍历到叶子节点,叶子节点代表的字符的编码就是这个路径编码。
|
||||
|
||||
上面的例子按下图编码,总长度为 250 位,每个字符固定 2 位则需要 300 位。因为字符都在叶子节点上,任何一个编码都不是另一个编码的前缀,解码时从根节点按位走到叶子节点就得到一个字符,不需要分隔符。
|
||||
|
||||
<div align="center"> <img src="pics/huffman-tree.png" width="620px"/> </div><br>
|
||||
|
||||
```java
|
||||
|
||||
Reference in New Issue
Block a user