遞迴演算法,是將問題轉化為規模縮小的同類問題的子問題,每乙個子問題都用乙個同樣的演算法去解決。一般來說,乙個遞迴演算法就是函式呼叫自身去解決它的子問題。
遞迴演算法的特點:
在函式過程中呼叫自身。
在遞迴過程中,必須有乙個明確的條件判斷遞迴的結束,既遞迴出口。
遞迴演算法簡潔但效率低,通常不作為推薦演算法。
function factorial (n)
return n * factorial(n-1);
}factorial(5)
如果乙個函式中所有遞迴形式的呼叫都出現在函式的末尾,我們稱這個函式是尾遞迴。當遞迴呼叫是整個函式體中最後執行的語句且它的返回值不屬於表示式的一部分時,這個遞迴呼叫就是尾遞迴。但是像上邊那樣遞迴會儲存很多個呼叫幀,比如上邊的factorial(5)
,這個方法要執行5次,才能返回最終的計算表示式,這樣每次都要儲存這個方法,就容易造成棧溢位。為了解決這個問題,我們會使用尾遞迴:
function factorial(n,total=1)
return factorial(n-1,n*total);
}factorial(5);
這樣,每一次返回的就是乙個新的函式,不帶上乙個函式的引數,也就不需要儲存上乙個函式了。只需要乙個幀即可。
問題描述: n! = n*(n-1)*...2*1
**實現:
var factorial = function(n)
console.log(factorial(5));
注:arguments.callee,是為了防止函式名的緊密耦合,在這裡它等同於factorial(n-1)。 在嚴格模式下,不能通過指令碼訪問arguments.callee,訪問這個屬性會報錯。
問題描述:1, 1, 2, 3, 5, 8, 13, 21, 34, ....... 求第n個數是多少。
**實現:
使用遞迴:
var fib = function(n)
return fib(n-1)+fib(n-2);
}console.log(fib(5));
使用迴圈:
var fib = function(n)
for(var i=0;i問題描述:一共10級樓梯,每次可以走一步或兩步,求一共多少種走法。
要想走到n(n=10)級,可以分為2種情況。
從n-2級邁兩步
從n-1級邁一步
那麼對於n-2和n-1的情況也是各自分為兩種,以此類推。那麼走法的和就是n-2的走法和n-1的走法之和。
實現**:
var fib = function(n)else if(n==2)else if(n>2)
}console.log(fib(10));
問題描述:給兩個數,如果兩個數相等,最大公約數是其本身。如果不等,取兩個數相減的絕對值和兩個數中最小的數比較,相等則為最大公約,不等則繼續上面的演算法,直到相等。
**實現:
var getnum = function(a,b)
console.log(getnum(12,15));
1)n(圓盤個數) == 1
第一次:1號盤 a -> c sum(移動次數) = 1
2)n == 2
第一次:1號盤 a -> b
第二次:2號盤 a -> c
第三次:1號盤 b -> c sum = 3
3)n == 3
第一次:1號盤 a -> c
第二次:2號盤 a -> b
第三次:1號盤 c -> b
第四次:3號盤 a -> c
第五次:1號盤 b -> a
第六次:2號盤 b -> c
第七次:1號盤 a -> c sum = 7
以此類推...
故不難發現規律,移動次數為:sum = 2^n - 1
把一堆圓盤從乙個柱子移動另一根柱子,必要時使用輔助的柱子。可以把它分為三個子問題:
首先,移動一對圓盤中較小的圓盤到輔助柱子上,從而露出下面較大的圓盤,
其次,移動下面的圓盤到目標柱子上
最後,將剛才較小的圓盤從輔助柱子上在移動到目標柱子上
把三個步驟轉化為簡單數學問題:
(1) 把 n-1個盤子由a 移到 b;
(2) 把 第 n個盤子由 a移到 c;
(3) 把n-1個盤子由b 移到 c;
**實現:
var haoni = function(n,src,aux,dest)
}haoni(3,"a","b","c");
問題描述:使用二分法,對乙個陣列進行由小到大的排序。
**實現:
function quicksort(arr)
}getparent(document.getelementbyid("node"));
console.log(arr);
問題描述:
定義乙個walk_the_dom函式:
1) 它從某個指定的節點開始,按指定html原始碼的順序,訪問樹的每個節點
2)它會呼叫乙個函式,並依次傳遞每個節點給它,walk_the_dom呼叫自身去處理每乙個節點
var walk_the_dom = function walk(node,func)
}
問題描述:
定義乙個getelementbyattribute函式:
1) 它以乙個屬性名稱字串和乙個可選的匹配值作為引數
2) 它呼叫walk_the_dom,傳遞乙個用來查詢節點屬性名的函式作為引數,匹配得節點都會累加到乙個陣列中
var getelementsbyattribute = function(att,value)
});return results;
}
問題描述:1個細胞,乙個小時**一次,生命週期是3小時,求n小時後容器內,有多少細胞。
細胞的生存週期是3個小時,那我們就可以把細胞在題目中狀態分為以下幾個狀態:
那麼,我們就可以根據細胞狀態設定函式。分析每乙個狀態的**是**即可。
容器中存活的細胞數目就是a、b、c三種狀態數量的總和。
var afib = function(n) //初始的那個細胞
return afib(n-1)+bfib(n-1)+cfib(n-1);
}var bfib = function(n) //乙個小時之後才會生成
return afib(n-1);
}var cfib = function(n)//前兩個小時還未生成
return bfib(n-1);
}var time = 3;
console.log(afib(time)+bfib(time)+cfib(time));
function flatten(arr)
return arr;
}
理解js遞迴演算法
遞迴演算法是一種看似簡單,但邏輯性比較複雜的演算法。一般我們看的遞迴 很複雜的問題3 4行就可以解決的,但是背後的邏輯還是很複雜的。遞迴的特點總結 1 自呼叫,就是在函式裡面呼叫自己 2 最關鍵的一點,就是乙個遞迴必須明確結束條件,不然就會陷入無窮的死迴圈 3 缺點,就是消耗大量記憶體 下面我們總結...
遞迴演算法實現
遞迴演算法 1 乙個人趕著鴨子去每個村莊賣,每經過乙個村子賣去所趕鴨子的一半又乙隻。這樣他經過了七個村子後還剩兩隻鴨子,問他出發時共趕多少只鴨子?經過每個村子賣出多少只鴨子?題目分析 遞迴終止的條件是到第7個村莊時遞迴停止 演算法構造 定義遞迴函式f n 當 n 8時 剩餘2只鴨子,當 0時 總共趕...
JS 函式的遞迴演算法
一 什麼是函式的遞迴 函式反覆呼叫自己,直到最終結果,跳出 var n 0 shownumber function shownumber shownumber 二 舉例 例1 遞迴階乘函式 function factorial num else 問題1 以上函式表面看起來沒有問題,但下面 會導致其出...