递归与尾递归

最近学习算法遇到一个很有意思的事情。
就是大家都知道递归用的不好是非常占内存而且耗时的。原因是因为递归函数是一层一层调用函数的。而在计算机中函数调用是通过栈(stack)这种数据结构实现,每当调用一层函数,栈就会加一层栈帧,每当函数返回,栈就会减少一层栈帧。所以递归用的不好可能会导致栈溢出。或者运行时间特别长。

优化递归的方法可以使用尾递归,事实上时间复杂度一样。尾递归主要是对栈内存空间优化,其实是由于对空间优化导致内存分配的工作减少产生。
而且可以把循环看成一种特殊的尾递归。
尾递归:在函数返回时只调用自身。尾递归在执行过程中不需要回溯。因为尾递归把结果包含在一部分参数中。故每次调用实际上都是对参数的一个更新过程。

//普通递归
    public static long fib_1(int n){
        if(n<=1){
            return 1;
        }
        return fib_1(n-1)+fib_1(n-2);
    }

    //尾递归
    public static long fib_2(int n){
        return fib_iter(1,1,n);
    }

    public static long fib_iter(long a,long b,int n){
        if(n<=0){
            return a;
        }
        return fib_iter(b,a+b,n-1);
    }

    //for循环
    public static long fib_3(int n){
        if(n<=1){
            return 1;
        }else{
            long fib=0;
            long a=1;
            long b=1;
            for(int i=1;i<n;i++){
                fib=a+b;
                a=b;
                b=fib;
            }
            return fib;
        }
    }


 //测试
    public static void main(String[] args) {
        int  NUM=40;
        long startTime1=System.currentTimeMillis();
        long m=fib_2(NUM);
        long endTime1=System.currentTimeMillis();
        System.out.println("fib_2:"+m);
        System.out.println("Time:"+(endTime1-startTime1));

        long startTime2=System.currentTimeMillis();
        long k=fib_3(NUM);
        long endTime2=System.currentTimeMillis();
        System.out.println("fib_3:"+k);
        System.out.println("Time:"+(endTime2-startTime2));

        long startTime=System.currentTimeMillis();
        long n=fib_1(NUM);
        long endTime=System.currentTimeMillis();
        System.out.println("fib_1:"+n);
        System.out.println("Time:"+(endTime-startTime));
    }

输出:
fib_2:165580141
Time:0
fib_3:165580141
Time:0
fib_1:165580141
Time:1556
可以看到for循环和尾递归还是非常快的。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值