寫程序這么久了,有時候別人會問道一些算法比如排序啊,遞歸啊,總是不知道該怎么去說,今天就來整理一下,讓更多的人去傻瓜式的理解遞歸。遞歸在網絡上有很多定義,但有這么一句話聽的最多:遞歸就是自己調用自己!引用百科的一個故事去理解:
從前有座山,山里有座廟,廟里有個老和尚,正在給小和尚講故事呢!故事是什么呢?“從前有座山,山里有座廟,廟里有個老和尚,正在給小和尚講故事呢!故事是什么呢?‘從前有座山,山里有座廟,廟里有個老和尚,正在給小和尚講故事呢!故事是什么呢?……’”
這樣的故事是不是在做很多重復的事情,像這樣的情況下就可以使用遞歸,遞歸需要幾個條件:
1,遞歸必須 要有邊界條件,也就是遞歸出口(退出遞歸)
2,遞歸前進段和遞歸返回段,也就是最后得到的值
3,當邊界條件(遞歸出口)不滿足時,遞歸前進;當邊界條件(遞歸出口)滿足時,遞歸返回。
舉個遞歸小例子,比如,
張三去和李四借錢,李四說你等一下,我去找王五借給你,
然后李四去找王五借錢,王五說你等一下,我去找趙六借給你,
最后王五找趙六借錢,趙六借給了王五。(這里就是遞歸出口)
這里有一個規律就是最先執行的最后返回,比如張三去借錢,最后才會把錢給他。
傻瓜式理解遞歸,就是忘記遞歸,假設它的子問題已經解決,從上面的例子說就是假設李四已經有錢。
下面說一個場景,斐波納契數列:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144
已知前兩項的和,求第三項的和,因為重復用到這個方法,所以用到遞歸去解:
斐波那契數列的規律是當前項等於前兩項的和,得到的公式是f(n)=f(n-1)+f(n-2);這里的n表示第幾項,上遞歸代碼:
這里假設子問題已經解決,加入求第10項的值公式為:f(10)=f(9)+f(8)故而出現上面的公式
function f($n){
if($n==1 || $n==2){
return 1; // 遞歸出口,
}
return f($n-1)+f($n-2); // 假設子問題已經解決
}
用迭代的方法求斐波那契數列:
function f($n){
$a = 1;
$b = 1;
$v = 1;
for($i=3;$i<=$n;++$i){
$v = $a+$b;
$b = $a;
$a = $v;
}
return $v;
}
大家常遇到的面試問題:一個猴子看一堆桃子,每天,吃了一半,又多吃一個!當到第十天時,只有一個桃子了。問題,有幾個桃子?
第十天,只有一個桃子,第九天就是(1+1)*2個桃子,假設子問題已經解決,f(1)=(f(2)+1)*2,第一天的桃子等於第二天桃子加1乘以2,上代碼:
/**
* 遞歸實現方法
*/
function f($n=1){
if($n==10){
return 1; // 遞歸出口
}
return (f($n+1)+1)*2;
}
/**
* 用迭代的方法
*/
function f($n){
$v = 1; // 設定初始值
for($i=9;$i>=$n;--$i){
$v = ($v+1)*2;
}
return $v;
}
echo f(1);
隨后會加一些遞歸的例子,待續,如果寫的有什么不清楚的地方,請批判我
