java 递归 时间复杂度_递归到底是怎么实现的?它的时间复杂度怎么算?
遞歸到底是個(gè)啥?
常聽見的一句話就是:自己調(diào)用自己。
按照這個(gè)說法,寫個(gè)簡單的遞歸自己推導(dǎo)一下的確可以,但是總是有點(diǎn)繞,推著推著自己把自己陷進(jìn)去了。
遞歸函數(shù)運(yùn)行時(shí),實(shí)際上會(huì)進(jìn)行一個(gè)壓棧(思考棧的特點(diǎn),先進(jìn)后出,后進(jìn)先出)的過程。
寫個(gè)簡單的遞歸排序算法:
public static voidmain(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,intR){if(L==R)returnarr[L];int mid=(L+R)/2;int LeftMax=digui(arr,L,mid);int RightMax=digui(arr,mid+1,R);returnMath.max(LeftMax,RightMax);
}
當(dāng)?shù)谝淮芜M(jìn)入digui方法時(shí),在第十行,也就是
int LeftMax=digui(arr,L,mid);
1.程序會(huì)第一次進(jìn)入到子方法,也就是調(diào)用本身。這時(shí)候會(huì)往堆棧里面記錄此時(shí)這個(gè)方法的信息,比如L=0,R=3,mid=1等等,并且暫停這個(gè)方法的繼續(xù)運(yùn)行,先進(jìn)入到子方法。
2.程序進(jìn)入子方法,第二次到第十行代碼時(shí),依舊會(huì)往堆棧里記錄此時(shí)的方法信息,L=0,R=1,mid=0等等
3.程序再次進(jìn)入子方法,第三次運(yùn)行到第十行代碼時(shí),此時(shí)L=0,R=0。所以會(huì)返回arr[0],也就是1.因?yàn)榉祷亓藬?shù)值,沒有再次調(diào)用自己,所以不用再次壓棧
此時(shí)的堆棧信息如圖
4.由于上一步返回了一個(gè)1,那么自然就會(huì)先回到其父方法,也就是L=0,R=1,mid=0的這個(gè)方法。這時(shí)候LeftMax就會(huì)接受到其子方法的返回的數(shù)據(jù),也就是1.
5.接著運(yùn)行第十一行代碼,繼續(xù)壓棧,然后運(yùn)行其子方法。自己捋一下,第十一行的子方法返回的是3
6.接著運(yùn)行第十二行代碼,會(huì)比較1和3誰大,然后返回。至此,L=0,R=1,mid=0時(shí)的這個(gè)方法徹底執(zhí)行完畢,接著就會(huì)執(zhí)行出棧操作。
有了堆棧圖的輔助,理清遞歸過程就清晰多了。大家可以自己捋一捋接下來幾步的過程。總比以前光憑一個(gè)腦袋想好多了。
遞歸的時(shí)間復(fù)雜度怎么算?
一般情況下,可以用以下公式:
T(N)=aT(N/b)+O(N^d);
其中,T是樣本,N的樣本量。
b代表這個(gè)樣本被分為了幾部分(上面的算法被分為兩部分(L+R)/2,所以b=2),a代表運(yùn)行了多少次(上面的算法需要調(diào)用自己兩次,所以a=2)。
一定要記住,這個(gè)a和b,不需要展開所有堆棧里的情況,只需要看最表面上的代碼就行,不用想里面的子方法還調(diào)用了多少次本身。
后面接著的O(N^d)代表除了前面那部分主體外,還需要多少時(shí)間復(fù)雜度,比如前面的aT(N/b)這部分運(yùn)行完,我還需要O(N^2)的時(shí)間復(fù)雜度才能最終完成輸出,那么d=2。
那么T(N)=aT(N/b)+O(N^d)到底怎么求出具體結(jié)果呢?
上面的算法中,a=2,b=2,d=0
所以log(b,a)=1.大于d的。所以時(shí)間復(fù)雜度為O(N)
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的java 递归 时间复杂度_递归到底是怎么实现的?它的时间复杂度怎么算?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 顺周期板块是指什么?顺周期板块能持续多久
- 下一篇: android 高斯模糊 c,c-如何在