在知乎上看到一个比较容易理解的
地址:https://www.zhihu.com/question/24385418
搞清楚递归只要搞清两点:
- 结束条件(递归出口)
- 把问题规模缩小
在什么是递归这个问题 李冰答主借用了网络上的一张图片,非常形象,此处引用一下
出口条件就是图中的小鲤鱼,规模缩小是找个除了规模更小其他都一模一样的自己
在汉诺塔问题中小鲤鱼就是只有一个盘子的时候
但是如何让自己规模缩小?
由于小的盘子不能在大的盘子上,最后一个盘子挪的时候前n-1个盘子必须已经被挪开,因此整个问题
被分为三步,如下
经过这样的分解,一个挪n个盘子的问题被转化为了: 两次挪n-1个盘子的过程加一个直接move的
过程。问题规模由n变为n-1,就可以继续缩小直到找到小鲤鱼---只剩一个盘子的情况
用js简单实现了,对照注释和前面的解析理解一下:
//把n个盘子借住helper从from柱子挪到to柱子上
function hanoi(n,from,to,helper){
//判断是否找到我们的小鲤鱼,找到我就直接返回,没找到我就把自己规模缩小
if(n==1){
console.log('move a plate from '+ from + ' to ' + to);
return;
}
hanoi(n-1,from,helper,to);//把n-1个从from挪到helper上,借助to
move(from,to);//把第n个盘子直接从from挪到to
hanoi(n-1,helper,to,from);//把n-1个从helper挪到from上,借助to
}
//把一个盘子从一个柱子挪到另一个柱子上
function move(from,to)
{
console.log('move a plate from '+ from + ' to ' + to);
}
最后划下重点:对于递归问题,要抓住两点:结束条件和如何让问题规模缩小问题。递归问题的正确性是根据数学归纳法来证明的,只要找到这两点也就可以使用数学归纳法了。
特别注意分析问题的时候不要让自己按着程序运行的顺序钻进去,这样会很容易困惑和乱掉,盯准关键两点,问题自然迎刃而解