汉诺塔问题一直是研究递归算法的一个经典案例,也被很多教材当成递归算法的进阶案列,今天,我们就来看一下这个汉诺塔问题!
首先明白什么叫汉诺塔问题:
首先有三个柱子:分别是
起始柱子(最左边): source
辅助柱子(最右边): helper
目标柱子(中间): dest
柱子上有诺干个盘子,我们通过移动让左右的盘子从小到大的堆放在目标柱子上(中间柱子)
下面是移动的动作
然后我们需要做的就是,写一个算法,把每次移动的动作放在一个数组里面,让算法计算怎么移动能达成目标,先看一下结果
看着这个
数组,是不是就能很清晰的看到是怎么走的了?哪怕有100个盘子,也能很快的计算出怎么走,只要根据数组上面的步骤执行就可以了
清楚了我们的目标,接下来一块写代码吧
我先把代码展示出来,然后再说明一下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
/**
* @param {圆盘数:number} plates
* @param {起始柱子 a:string} source
* @param {辅助柱子 b:string} helper
* @param {目标柱子 c:string} dest
* @param {移动步骤集:Array,数组的长度就是移动的次数} moves
*/
var move1 = []
function hanoi(plates, source, helper, dest, moves = []) {
if (plates <= 0) {
return moves;
}
if (plates === 1) {
moves.push([source, dest]);
move1.push([source, dest, helper]);
} else {
hanoi(plates - 1, source, dest, helper, moves);
moves.push([source, dest]);
hanoi(plates - 1, helper, source, dest, moves);
}
return moves;
}
// test
console.log(hanoi(5, 'source', 'helper', 'dest')); // 输出结果如下图展示
</script>
</html>
最难的是else里面的两次递归调用,这个不太好讲,我做了个图,帮助理解!
5层的汉诺塔太大了,不太好截图,我放个4层的,其实原理是一样的,
4层就是2的四次方-1,也就是15次;
5层就是2的5次方-1,得到31次;
这个不太好理解,也得花时间,我当时搞了一晚上,才画出的图,有兴趣的小伙伴可以私我,大家一块讨论,如果有不正确的地方,欢迎大家伙指导!