对递归的思考和错误记录
首先是汉诺塔
汉诺塔也是算法问题里面的Hello World了,也还是自己过一遍手
首先递归最关键的理解就是对于递归函数的“信任”,用Eric S Roberts那本书的中二翻译的话来说就是“递归的信任飞跃”。我觉得递归的思路很像数学归纳法,以斐波拉契数列为例,递归式实际上就是数学归纳法的表达式。所以我觉得递归的思路可以这样整合:
1.假定一个函数可以达到一个中间子过程
2. 分析该中间子过程,找到一个合适的方法去从当前子过程状态到下一个子过程状态
然后用这种想法去试试汉诺塔呢
我要把n个盘从A放到C去
考虑一个中间过程,假设我有一种方法可以将n块转移到B去,之后就开始描述从n到n+1 过程的实现,简直像极了数学归纳法
而这个过程,需要再将n块从A转移到C,将第n+1块从A转移到B,再将n块从C转移到B,这就实现了从n到n+1的情况
为了让方法具有普遍性,我们将之前描述的方法把n块转移到B改成有一种方法可以将n块木板从start这个柱子通过temp柱子到finish柱子
我觉得这个表述才是汉诺塔递归算法里面最关键的一步,因为它确定了一个普适性的方法,而从A到B和A到C之类的只是改变的参数了。
最后再写出出口,即n==1 时的情况。显然此时,只需要将该木块从start柱子移到finish柱子去就是了。
代码如下:
public class hannuo{
public static void main(String[] args){
long begintime=System.nanoTime();
Hannuo(46, 'A', 'B','C');
long endtime = System.nanoTime();
long costTime = (endtime - begintime)/1000/1000;
//要换算为微秒,就除上1000,就可以
System.out.println("代码用时:"+costTime+"ms");
}
//写一个函数,给定移动的木桩参数去移动
public static void Hannuo(int n,char from,char cross ,char to){
if(n==1)System.out.println(from+"移到"+to);
else{
//开始写从状态n到状态n+1的实现过程
Hannuo(n-1,from,to,cross);
System.out.println(from+"移到"+to);
Hannuo(n-1,cross,from,to);
}
}
}
递归就是多给了一个方法,你不用去细究他究竟是如何实现的,只管去用就是了。
当然,还是可以理一下函数栈究竟是如何调用的,我也可以再自己理一理思路。但我个人认为这是一种不太对的递归思维方式。如果递归去细究,那递归就失去了其本身的简洁美了。对了,说道这里,上面那个程序已经运行了十五分钟了,我还是没有给出答案。我现在怀疑我用s为单位输出时间会不会溢出。。。
。。。
十分钟后我发现好难照着书上画栈的图啊,所以就。。。算了吧。
后面再添一些其他我觉得有意思的递归题8