算法:递归

来源:互联网 发布:java打包war后如何发布 编辑:程序博客网 时间:2024/06/05 23:48

递归算法一直就是个很难理解的问题,这个问题确实是非常的复杂,就算是计算机,以他的运行速度去解决递归问题也会是非常的难。
递归就是函数本身调用本身,说白了就是已知前一项的结果就能够很直接的得到当前项的结果。所以递归可以解决所有的数列问题。所以递推也可以用递归来解决。但是不推荐使用递归。因为递归的执行速率太低。但是当我们遇到了一些问题没有办法去描述,用递归的办法就可能会很容易的解决了这个问题。
比如汉诺塔问题:
如何去描述这个规律呢,如何将n个盘子通过中间柱移到目标柱。
这个问题没有办法去描述,但是可以将汉诺塔问题抽象为,首先将n-1个盘子通过目标柱移到中间柱,然后将第n个盘子移到目标柱,最后再将n-1个盘子移到目标柱。这样我们就解决了这个问题。当只有一个盘子的时候我们是知道怎么移动的。
js解决递归问题:

var n = Number(prompt("请输入盘子的个数"));var step = 0;move(n);alert(n+"次可以将盘子移动到目标柱");function move(n){    if(1 == n){        step ++;        return ;    }else{        move(n-1);        step ++;        move(n-1);    }}

再举个例子:
上台阶的问题:已知上台阶可以一步上一个台阶也可以一步上两个台阶。问n个台阶有多少种上法。

这个问题也是好像没有什么好的方式去描述。但其实已知
当只有1个台阶只有1种上法,只有2个台阶有2种上法
假设这个人就迈一步,这一步有两种可能就是一步上一个台阶和一步上两个台阶
那么这个问题就可以直接写为:

var n = Number(prompt("请输入台阶的个数"));var sum = go(n);alert("总共有"+sum+"种上台阶的方法");function go(n){    if(n==1 || n==2){        return n;    }else{        go(n-1) + go(n-2);    }}

总结:对于递归问题
首先要确定已知的值
在汉诺塔中已知的值就是:当只有一个盘子的时候就只有一个走法。
然后就是找到n和n-1的关系(就是降阶)将复杂的问题简单化。
在汉诺塔中:假设知道了n-1种走法,接下来就是把最大的盘子移到目标柱然后再把n-1个盘子移到目标柱。

再举个例子:猴子选大王问题,一圈猴子,选大王报数,报的数为3就自动退出,直到最后一只猴子当选为猴王。

这个问题怎么描述:
假设只有一个猴子的时候就是0号猴子当选了。
当我们知道n-1个猴子的是如何选猴王的时候,我们很容易的就知道了n个猴子是谁当选了。这个时候可以去试试,举例当有3个猴子谁当选,加进来1只猴子之后谁当选。其实关系就是当前的猴子+3后面的那只猴子当选。
js实现代码为

function selectKing(n){    if(1 == n){        return 0;    }else{        (selectKing(n-1)+3)%n;    }}var n = Number(prompt("请输入一个数"));var king = selectKing(n);alert(king+1+"号猴子当选");

其实汉诺塔问题也是一个数列

盘子的个数 移动的次数 1 1 2 3 3 7

其实移动的次数也就是2的n次方-1

那台阶的问题:

台阶的个数 移动的方法 1 1 2 2 3 3 4 5

台阶移动方法的个数就是数列的前两项的和

猴子选大王的问题

猴子的个数 大王的编号 1 0 2 1 3 1 4 0

猴子大王就是前一项的大王编号+3对猴子的个数取余的结果

其实递归就是解决某种有数列的简单的方式,但是他的计算得速率比较慢,但是从大局的角度去理解,递归是非常简单的方式。只要对函数有深刻的理解。就能很好的利用递归。都是理论上说函数调用函数的效率比较低。但是 我并没有去测验,之后有时间我会去再做一个测验看看两者的效率到底有什么区别,如果区别不大,也可以使用递归去解决。表面上看,我输入一个汉诺塔的次数为200会运行好一会但是如果使用公式计算2的200次方 很快就计算出来了。所以递归的效率应该还是比较低的。所以尽量的少使用递归!

原创粉丝点击