JS實現階乘以及使用遞迴
初略一看,的確遞迴實現階乘很簡單,不過很好的實現遞迴還是需要一點技巧的。
遞迴即是程式在執行過程中不斷調用自身的編程技巧,當然也必須要有一個明確的結束條件,不然就停不下來了好麼~ 這邊就簡單的實現一下遞迴的階乘。
- function factorial( n ){
- return ( n <= 1 ) ? 1 : n * factorial( n-1 );
- }
對於階乘遞迴來說,由於其每次僅僅遞迴調用自身一次,所以不會引起一些較大的問題,但是對於一些相對一些相對複雜的遞迴,做一些技巧性的緩衝還是很有必要的。比如遞迴最經典的使用情境就是計算斐波那契數列,但是每次調用過程中會在此調用自身函數兩次,於是乎,2變4,4變8,量級成2指數級增長,當計算一些稍大的數時,便會遇到一些已耗用時間,或者有可能導致棧溢出。
- function fibonacci( n ){
- return ( n <= 2 ) ? 1 : fibonacci( n-1 ) + fibonacci( n-2 );
- }
- function t(n){
- console.time("a");
- console.log( fibonacci( n ));
- console.timeEnd("a");
- }
上面便是具體資料,的確貌似有那麼點的消耗大了點,畢竟才算到 42 就要 2s,畢竟測試的機子也算是中上級的,那麼最佳化方式可以先使用緩衝方式試試:
- var fibArr = [ undefined, 1, 1 ];
- function fibonacci( n ){
- var nFib = fibArr[ n ];
- return nFib
- ? nFib
- : ( fibArr[ n ] = fibonacci( n-1 ) + fibonacci( n-2 ) );
- }
好吧,不多解釋,這就是最佳化的結果。仔細想想可以感受到,我們將斐波那契數的計算量級從 2的指數 次級,降到了常量 n 次級,並且由於緩衝,在多次運行將量級降得更低,然後運行速度簡直把我和小夥伴都驚呆了。並且該方法也很好的緩解了棧溢出問題。
要是沒記錯的話,有個理論是 所有的遞迴迴圈都可以轉化成迭代迴圈
- function fibonacci( n ){
- var x = 1, y = 1, i=2, t;
- while( i < n ){
- t = y;
- y = x + y;
- x = t;
- i++;
- }
- return y;
- }
貌似這下有點更牛逼了,其實他的量級與最佳化後帶緩衝的遞迴式一樣的,不過他的量僅僅是計算,而遞迴的每個量都是調用一次方法,這也是兩者最大的差別。
好吧,自己的看法就簡單的這麼講一下,關於遞迴方式,需要考慮仔細,一招棋下不好,就癱了。不專業的屬於方面請大家多多諒解,有錯誤歡迎指正,謝謝。