遞歸1-初識遞歸

?才畢業(yè)的開發(fā)小白纠俭,最近在使用node沿量、php和vue,有興趣的小伙伴可以加群 134246716冤荆,大家一起學(xué)習(xí)欧瘪,這是一個新建群,有興趣的初學(xué)者可以來一起學(xué)習(xí)哦匙赞。

I. 遞歸簡論
  • 遞歸的概念
    當(dāng)一個函數(shù)用它自己來定義時(shí)就稱為是遞歸(recursive)的。
  • 遞歸的基本法則
    當(dāng)編寫遞歸程序時(shí)妖碉,關(guān)鍵是要牢記遞歸的四條基本法則:
    1.基準(zhǔn)情形 (base case)涌庭。必須總要有某些基準(zhǔn)情形,它無需遞歸就可以解出欧宜。
    2.不斷推進(jìn) (making progress)坐榆。對于那些需要遞歸的求解的情形,每一次遞歸調(diào)用都必須要使情況朝向一種基準(zhǔn)情形推進(jìn)冗茸。
    3.設(shè)計(jì)法則 (design rule)席镀。假設(shè)所有的遞歸調(diào)用都能運(yùn)行。
    4.合成法則 (compound interest rule)夏漱。在求解一個問題的同一實(shí)例時(shí)豪诲,切勿在不同的遞歸調(diào)用中做重復(fù)性的工作。
    ?使用遞歸計(jì)算諸如斐波那契數(shù)之類簡單數(shù)學(xué)函數(shù)的值的想法一般來說不是一個好主 意挂绰,其道理正是根據(jù)第四條法則屎篱。
II. 遞歸與數(shù)學(xué)歸納法
  • 數(shù)學(xué)歸納法的思想

    ?一般地,證明一個與自然數(shù) n 有關(guān)的命題 P(n)葵蒂,有如下步驟:
    (1) 證明當(dāng) n 取第一個值 n0 時(shí)命題成立;
    (2) 假設(shè)當(dāng)n=k(k?n0)時(shí)命題成立交播,證明當(dāng)n=k+1時(shí)命題也成立。
    綜合(1)(2)践付,對一切的自然數(shù) n(n ? n0)秦士,命題 P(n) 都成立。
    其實(shí)永高,數(shù)學(xué)歸納法利用的是遞推的原理隧土,可以形象地叫做多米諾原理。 數(shù)學(xué)歸納法的關(guān)鍵就是如何證明當(dāng) n = k + 1 時(shí)命題也成立命爬。

  • 遞歸的思想

    ? 很明顯次洼,遞歸也是用了遞推的思想。
    (1) 首先遇骑,我們需要一個遞歸的出口卖毁,即 base case;
    (2) 其次,是遞歸體的設(shè)計(jì),即對于一個一般的情況如何向 base case 靠近亥啦,把它化解成為一個更小的炭剪,同樣結(jié)構(gòu)的問題。
    遞歸的關(guān)鍵就是將問題轉(zhuǎn)化成一個更小規(guī)模的同樣結(jié)構(gòu)的問題翔脱。

III. 遞歸的經(jīng)典例子
  • n!的遞歸算法
    ? 求解 n! 是最經(jīng)典入門的遞歸算法奴拦。根據(jù)前面的知識我們知道用遞歸解決這個問題,需要兩個要點(diǎn)届吁。首先错妖,如何將一個大的問題轉(zhuǎn)化成一個小規(guī)模的問題?我們知道,n! = n(n ? 1)!疚沐, 那么根據(jù)這個公式暂氯,我們就可以輕易地將求解 n! 轉(zhuǎn)化為求解 (n ? 1)!(將問題的規(guī)模變小了,并且是同樣的問題)亮蛔。其次痴施,如何找到 base case,即遞歸的出口呢?在該問題里面也是很明顯的究流,最后求 1! 時(shí)辣吃,就不需要在遞歸了。所以芬探,該遞歸算法可以寫為:
int factorial(int n){
   if (n == 1)
       return 1; // base case
   return n * factorial(n ? 1); // making progress
}
  • 漢諾塔的遞歸算法
    ? 如下圖所示神得,從左到右 A、B偷仿、C 三根柱子循头,其中 A 柱子上面有從小疊到大的 n 個圓盤。 現(xiàn)要求將 A 柱子上的圓盤移到 C 柱子上去炎疆,期間只有一個原則:一次只能移到一個盤子且大盤子不能在小盤子上面卡骂,求移動的步驟和移動的次數(shù)。
    漢諾塔示意圖.png

    1. 算法分析:
    ? 當(dāng) A 柱子上只有一個盤子時(shí)形入,可以直接把盤子移到 C 柱子上;當(dāng) A 柱子上有兩個盤子時(shí)全跨,需要借助 B 盤子,先將上面的小盤子移到 B 柱子上亿遂,再將大盤子移到 C 柱子上浓若,再將小盤子移到 C 柱子上。那對于更一般的情況蛇数,當(dāng)有 n 個盤子的時(shí)候怎么遞歸呢?當(dāng)有 n 個盤子時(shí)挪钓,我們可以將盤子看成兩個部分。第 n 個盤子和上面 n ? 1 個盤子耳舅,如圖中的顏色區(qū)分碌上。就像是操作兩個盤子(把前 n ? 1 個盤子看成一個整體):先把前 n ? 1 個盤子從 A 盤放到 B 盤倚评,再把第 n 個盤子從 A 盤放到 C 盤,最后再把前 n ? 1 個 盤子從 B 盤放到 C 盤馏予。這樣我們就把問題的規(guī)奶煳啵縮小到 n ? 1 了。
    2. 算法的Java實(shí)現(xiàn):
/**
 * @Author: 落腳丶
 * @Date: 2017/10/14
 * @Time: 下午8:33
 * @ClassName: HanoiTower
 * @Description: 漢諾塔的遞歸算法
 */

import java.util.Scanner;

public class HanoiTower {
    private static int step = 0; // 記錄步數(shù)

    public static void main(String[] argus){
        Scanner scanner = new Scanner(System.in);
        System.out.println("請輸入盤子的個數(shù):");
        int count = scanner.nextInt();
        hanoi(count, 'A', 'B', 'C');
    }
    /**
    * @Date: 2017/10/14
    * @Time: 下午9:27
    * @Method: hanoi
    * @Description:
     * 將n個盤子從a塔移動到c塔霞丧,需要借助中間塔b呢岗。
     * 最后一個塔只需要直接移動即可
     *
    */
    private static void hanoi(int n, char a, char b, char c){
        /**
         * n為需要移動的盤子數(shù);
         * a是最開始放盤子的塔蛹尝;
         * b是中間中轉(zhuǎn)的塔后豫;
         * c是最終需要放盤子的塔。
         */
        if (n == 1) {
            // 遞歸的base case 只有一個盤子的時(shí)候突那,直接把盤子從a塔移到c塔
            move(1, a, c);
        }else {
            /**
             * 對于遞歸的一般情況挫酿,把前n-1個塔看做是一個整體,整體移動陨收,
             * 那么現(xiàn)在就相當(dāng)于兩個塔,
             * 注意:hanoi(n, a, b, c)方法的含義就是利用中間塔b鸵赖,
             * 把n個盤子從a塔移到c塔务漩!
             * 我們只需要下面三步:
             * 1. 把前n-1個盤子,從a塔移到b塔它褪,需要借助中間塔c饵骨;
             * 2. 把第n個盤子從a塔移到c塔;
             * 3. 把前n-1個盤子從b塔移到c塔茫打,需要借助中間塔a居触。
             */
            hanoi(n - 1, a, c, b);
            move(n, a, c);
            hanoi(n - 1, b, a, c);
        }
    }
   private static void move(int number,char origin, char target){
        System.out.println("第" + ++step + "次移動:" + number +
                "號盤子," + origin + " ----> " + target);
    }
}
/**
 * 以3個盤子為例的輸出:
 *
 * 請輸入盤子的個數(shù):
 * 3
 * 第1次移動:1號盤子老赤,A ----> C
 * 第2次移動:2號盤子轮洋,A ----> B
 * 第3次移動:1號盤子,C ----> B
 * 第4次移動:3號盤子抬旺,A ----> C
 * 第5次移動:1號盤子弊予,B ----> A
 * 第6次移動:2號盤子,B ----> C
 * 第7次移動:1號盤子开财,A ----> C
 */

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末汉柒,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子责鳍,更是在濱河造成了極大的恐慌碾褂,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件历葛,死亡現(xiàn)場離奇詭異正塌,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評論 3 385
  • 文/潘曉璐 我一進(jìn)店門传货,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缚甩,“玉大人电谣,你說我怎么就攤上這事。” “怎么了切油?”我有些...
    開封第一講書人閱讀 157,435評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長烹玉。 經(jīng)常有香客問我叁幢,道長,這世上最難降的妖魔是什么巍杈? 我笑而不...
    開封第一講書人閱讀 56,509評論 1 284
  • 正文 為了忘掉前任忧饭,我火速辦了婚禮,結(jié)果婚禮上筷畦,老公的妹妹穿的比我還像新娘词裤。我一直安慰自己,他們只是感情好鳖宾,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,611評論 6 386
  • 文/花漫 我一把揭開白布吼砂。 她就那樣靜靜地躺著,像睡著了一般鼎文。 火紅的嫁衣襯著肌膚如雪渔肩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,837評論 1 290
  • 那天拇惋,我揣著相機(jī)與錄音周偎,去河邊找鬼。 笑死撑帖,一個胖子當(dāng)著我的面吹牛蓉坎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播胡嘿,決...
    沈念sama閱讀 38,987評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼袍嬉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了灶平?” 一聲冷哼從身側(cè)響起伺通,我...
    開封第一講書人閱讀 37,730評論 0 267
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎逢享,沒想到半個月后罐监,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,194評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瞒爬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,525評論 2 327
  • 正文 我和宋清朗相戀三年弓柱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了沟堡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,664評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡矢空,死狀恐怖航罗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情屁药,我是刑警寧澤粥血,帶...
    沈念sama閱讀 34,334評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站酿箭,受9級特大地震影響复亏,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜缭嫡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,944評論 3 313
  • 文/蒙蒙 一缔御、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧妇蛀,春花似錦耕突、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至古程,卻和暖如春蔼卡,著一層夾襖步出監(jiān)牢的瞬間喊崖,已是汗流浹背挣磨。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留荤懂,地道東北人茁裙。 一個月前我還...
    沈念sama閱讀 46,389評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像节仿,于是被迫代替她去往敵國和親晤锥。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,554評論 2 349

推薦閱讀更多精彩內(nèi)容