/**
* java version "1.6.0_17"<br>
* 尾递归与迭代实现具有相当的性能;<br>
* 缓存实现的性能略高于非尾递归实现;<br>
* 递归:recursive 尾递归:tail recursive;<br>
* 尾递归时不需保存方法调用栈的参数及返回结果;于是申请的栈帧会被及时回收
*/
public class TestFibo {
public static void main(String[] args) {
int N=50;
long begin=System.currentTimeMillis();
System.out.println(fibo1(N)); //fibo1
System.out.println(System.currentTimeMillis()-begin);
begin=System.currentTimeMillis();
System.out.println(fibo2(N)); //fibo2
System.out.println(System.currentTimeMillis()-begin);
begin=System.currentTimeMillis();
System.out.println(fibo3(N)); //fibo3
System.out.println(System.currentTimeMillis()-begin);
begin=System.currentTimeMillis();
System.out.println(fibo4(N)); //fibo4
System.out.println(System.currentTimeMillis()-begin);
}
//1.1 非尾递归实现(书本上经常出现)
public static long fibo1(long n){
if(n<2) return n;
return fibo1(n-1)+fibo1(n-2); //小心栈溢出
}
//1.2 缓存实现(JS good part里有过介绍)
public static int LENGTH=30; //过大了就会占用过多空间
public static long[] cache=new long[LENGTH];
public static long fibo2(int n){
if(n<2) return n;
if(n>=LENGTH){
return fibo2(n-1)+fibo2(n-2);
}else if(cache[n]==0){
cache[n]=fibo2(n-1)+fibo2(n-2); //减少重复计算
}
return cache[n];
}
//1.3 迭代实现
public static long fibo3(long n){
if(n<2) return n;
long pre=1,prepre=1,ret=0;
for(int i=2;i<n;i++){
ret=pre+prepre;
prepre=pre;
pre=ret;
}
return ret;
}
//1.4 尾递归实现
public static long fibo4(int n){
if(n<2) return n;
return fibo4Helper(n, 1, 1, 3); //保持与非尾递归接口不变,是借助帮助方法实现尾递归的
}
private static long fibo4Helper(int n,long prepre,long pre,int begin){
if(n==begin) return pre+prepre;
return fibo4Helper(n, pre, prepre+pre, ++begin); //这里相当于迭代实现for-loop的浓缩
}
//----------------------尾递归的其他实现-------------------------------------->
//2. 求最大公约数
public static int gcd(int big,int small){
if(big%small==0) return small;
return gcd(small, big%small);
}
//3.1 阶乘--非尾递归
public static int fn1(int n){
if(n<2) return 1;
return n*fn1(n-1);
}
//3.2 阶乘--尾递归
public static int fn2(int n){
if(n<2) return 1;
return fn2Helper(1, n);
}
private static int fn2Helper(int ret, int n){
if(n<2) return ret;
return fn2Helper(ret*n,n-1);
}
//4.1 翻转字符串--非尾递归
public static String reverse1(String s, int length){
if(length==0) return ""; //下一行的"+"可借助高版本JDK编译器的优化
return s.charAt(length-1)+reverse1(s,length-1);
}
//4.2 翻转字符串--尾递归
public static String reverse2(String s){
return reverse2Helper(s, "", s.length());
}
private static String reverse2Helper(String s,String init,int len){
if(len==0) return init;
return reverse2Helper(s, init+s.charAt(len-1), len-1);
}
//5. 验证字符串是否是回文 testHuiwen("abcdcba")
public static boolean testHuiwen(String s){
return testHuiwenHelper(s, 0, s.length());
}
private static boolean testHuiwenHelper(String s,int begin, int len){
if(begin< len>>1 && s.charAt(begin)==s.charAt(len-begin-1))
return testHuiwenHelper(s, begin+1, len);
else if(begin==len>>1) return true;
else return false;
}
//6. 翻转整数 如:1024=>4201
public static int reverseInt(int i){
return reverseIntHelper(i, 0);
}
private static int reverseIntHelper(int i, int init){
if(i==0) return init;
return reverseIntHelper(i/10, init*10+i%10);
}
}
最后show一下强大的scala,用一行代码获取斐波那契数列的前30位:
>(1 to 28).foldLeft("0,1")((a,b)=>a+","+a.split(",").takeRight(2).map(_.toInt).reduceLeft(_+_))
>0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368,75025,121393,196418,317811,514229
>(1 to 28).foldLeft(List(1,0))((a,b)=>(a.head+a.tail.head)::a).reverse.mkString(",")
>0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368,75025,121393,196418,317811,514229
scala> def fibo(n:Int)=(1 to n).foldLeft(List(0,1))((a,b)=>a:+(a.init.last+a.last))
fibo: (n: Int)List[Int]
scala> fibo(10)
res4: List[Int] = List(0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89)
材料备注:
http://hi.baidu.com/donghongchen/blog/item/989089f1409caea3a50f5254.html
分享到:
相关推荐
斐波那契数 尾递归 递归 循环 typedef int (*fabFunc)(int); int fabonacci(int n); int fabonacci1(int n);//递归 int fabonacci2(int n);//循环实现 int fabtrail(int n,int a,int b);//尾递归实现 void timing...
#### 四、尾递归的应用场景及注意事项 尾递归非常适合用于那些需要大量递归调用且每个递归层次之间的计算量较小的场景。例如,在处理树形数据结构或进行深度优先搜索等算法时,使用尾递归可以显著提高性能。 然而...
在Java中实现斐波那契数列的前n项和,我们通常会采用几种不同的方法,每种方法都有其优缺点。下面将详细介绍这几种实现方式: 1. **递归法**: 这是最直观的方法,但效率最低。递归公式为F(n) = F(n-1) + F(n-2)。...
另一种优化循环的方法是使用尾递归,不过C++标准并未要求编译器对尾递归进行优化,因此这取决于具体的编译器实现。 6. **闭式公式**: 斐波那契数列可以通过黄金分割比例的闭式公式计算,但这在大整数情况下可能...
因此,非尾递归或深度较大的递归可能需要优化,如使用迭代代替或者尾递归优化。 - **终止条件**:确保每个递归调用都向基础情况靠近,否则可能会导致无限递归。 - **理解问题与分解**:正确理解和分解问题是成功...
3. 尾递归:在某些语言中(如Scheme、Haskell),尾递归是指递归调用是函数体的最后一个操作,这样的递归可以被优化为迭代,避免栈溢出。 五、实例分析 以计算斐波那契数列为例,其递归实现如下: ```python def ...
3. **尾递归优化**:在某些语言中,如Scala或Haskell,可以利用尾递归特性来优化递归算法,使得其运行效率接近于循环。 4. **数学公式**:对于斐波那契数列,存在闭合形式的解,即著名的Binet公式,虽然在实际编程...
6. **尾递归优化**:某些Java编译器支持尾递归优化,这允许在不增加额外堆栈空间的情况下进行递归调用。不过,Java标准版目前并不默认开启这一优化,但在Java 14及以上版本的JDK中,可以使用`@jdk.internal.vm....
为了解决这些问题,可以使用尾递归优化、记忆化搜索(存储之前计算过的值)或者完全转换为迭代方法。 从提供的压缩包文件名"递归"和"递归1"来看,可能包含了两段不同的递归实现。可能是上述的阶乘和斐波那契序列,...
针对递归算法中存在的性能问题,我们可以通过以下几种方式对其进行优化: ##### 3.1 记忆化(Memoization) **定义**:记忆化是一种将计算结果存储起来以供后续查询的技术,主要用于减少重复计算。在递归算法中,...
8. **阶乘的递归实现**:展示了两种实现阶乘的递归函数,一种是常规递归,另一种是尾递归优化的形式。尽管Python未对尾递归优化,理解尾递归的概念仍然有助于编写更高效和简洁的代码。 9. **函数返回值**:Python...
为了优化递归,可以考虑使用尾递归(tail recursion),即递归调用成为函数体的最后一个操作,编译器可以优化为迭代形式。另外,使用记忆化技术(memoization)可以避免重复计算,提高效率。 总结起来,C++中的递归...
- 尾递归:在递归调用是函数的最后一条语句且没有其他操作时,称为尾递归,一些编程语言支持优化尾递归,以避免栈溢出。 6. **递归模型的概念**: 递归模型是抽象出递归算法的通用框架,它描述了问题的结构和递归...
同时,通过适当优化,如尾递归(在递归调用的最后返回,无需额外的操作),可以减少不必要的开销。 在提供的“递归实例代码”文件中,可能会包含各种使用递归解决问题的实际示例,比如上述提到的排序算法、树遍历等...
除了以上方法,还可以使用生成器、尾递归优化等技术来实现斐波那契数列。在实际应用中,选择哪种方法取决于具体需求,如性能、内存限制和代码可读性等因素。 了解如何在Python中生成斐波那契数列后,可以进一步探索...
5. **性能优化**:如果可能,源码可能会包含一些优化措施,如尾递归、记忆化等,以提高算法效率。 要深入理解这段源码,需要具备易语言的基础知识,以及对递归和二进制运算的理解。通过分析源码,我们可以学习到...
在易语言中,可以通过尾递归优化、记忆化(存储已计算过的子问题结果)等方式提高递归算法的性能。 6. **应用示例**:递归算法在易语言中可以应用于多种场景,如: - **斐波那契序列**:计算斐波那契数列的第n项,...
1. **尾递归**:将递归转换为尾递归形式,减少重复计算。 2. **记忆化**:使用缓存机制来保存已经计算过的结果,避免重复计算。 3. **非递归实现**:对于某些递归算法,可以使用迭代等非递归的方式重新实现,以减少...
因此,对于可能造成深度递归的问题,需要特别注意或采用尾递归优化。 3. **正确设置基础情况**:确保每个递归调用最终都能到达基础情况,否则程序将陷入无限递归。 4. **避免重复计算**:在一些问题中,如斐波那契...
另外,尾递归是一种特殊的递归形式,它在递归调用的最后返回,编译器或解释器有时能对其进行优化,使其等效于循环,从而减少栈空间的使用。 总的来说,递归算法是编程中不可或缺的一部分,理解和掌握递归可以帮助...