递归到底是怎么实现的?它的时间复杂度怎么算?

递归到底是个啥?

常听见的一句话就是:自己调用自己。

按照这个说法,写个简单的递归自己推导一下的确可以,但是总是有点绕,推着推着自己把自己陷进去了。

递归函数运行时,实际上会进行一个压栈(思考栈的特点,先进后出,后进先出)的过程。

写个简单的递归排序算法:

public static void main(String[] args) {
        int[] arr={1,3,4,2};
        System.out.println(digui(arr,0,arr.length-1));
    }

    public static int digui(int[] arr,int L,int R){
        if(L==R)
            return arr[L];
        int mid=(L+R)/2;
        int LeftMax=digui(arr,L,mid);
        int RightMax=digui(arr,mid+1,R);
        return Math.max(LeftMax,RightMax);
    }

当第一次进入digui方法时,在第十行,也就是

int LeftMax=digui(arr,L,mid);

1.程序会第一次进入到子方法,也就是调用本身。这时候会往堆栈里面记录此时这个方法的信息,比如L=0,R=3,mid=1等等,并且暂停这个方法的继续运行,先进入到子方法。

2.程序进入子方法,第二次到第十行代码时,依旧会往堆栈里记录此时的方法信息,L=0,R=1,mid=0等等

3.程序再次进入子方法,第三次运行到第十行代码时,此时L=0,R=0。所以会返回arr[0],也就是1.因为返回了数值,没有再次调用自己,所以不用再次压栈

此时的堆栈信息如图

4.由于上一步返回了一个1,那么自然就会先回到其父方法,也就是L=0,R=1,mid=0的这个方法。这时候LeftMax就会接受到其子方法的返回的数据,也就是1.

5.接着运行第十一行代码,继续压栈,然后运行其子方法。自己捋一下,第十一行的子方法返回的是3

6.接着运行第十二行代码,会比较1和3谁大,然后返回。至此,L=0,R=1,mid=0时的这个方法彻底执行完毕,接着就会执行出栈操作。

有了堆栈图的辅助,理清递归过程就清晰多了。大家可以自己捋一捋接下来几步的过程。总比以前光凭一个脑袋想好多了。

 

递归的时间复杂度怎么算?

一般情况下,可以用以下公式:

T(N)=aT(N/b)+O(N^d);

其中,T是样本,N的样本量。

b代表这个样本被分为了几部分(上面的算法被分为两部分(L+R)/2,所以b=2),a代表运行了多少次(上面的算法需要调用自己两次,所以a=2)。

一定要记住,这个a和b,不需要展开所有堆栈里的情况,只需要看最表面上的代码就行,不用想里面的子方法还调用了多少次本身。

后面接着的O(N^d)代表除了前面那部分主体外,还需要多少时间复杂度,比如前面的aT(N/b)这部分运行完,我还需要O(N^2)的时间复杂度才能最终完成输出,那么d=2。

那么T(N)=aT(N/b)+O(N^d)到底怎么求出具体结果呢?

上面的算法中,a=2,b=2,d=0

所以log(b,a)=1.大于d的。所以时间复杂度为O(N)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值