爬樓梯問(wèn)題【多解法】

假設(shè)你正在爬樓梯馋吗。需要 n 階你才能到達(dá)樓頂缺猛。
每次你可以爬 1 或 2 個(gè)臺(tái)階拷沸。你有多少種不同的方法可以爬到樓頂呢中姜?
注:n 是一個(gè)正整數(shù)消玄。

示例 1:

輸入: 2
輸出: 2
解釋?zhuān)?有兩種方法可以爬到樓頂。

  1. 1 階 + 1 階
  2. 2 階
示例 2:

輸入: 3
輸出: 3
解釋?zhuān)?有三種方法可以爬到樓頂丢胚。

  1. 1 階 + 1 階 + 1 階
  2. 1 階 + 2 階
  3. 2 階 + 1 階

方法一:暴力法

在暴力法中翩瓜,我們將會(huì)把所有可能爬的階數(shù)進(jìn)行組合,也就是 1 和 2 携龟。而在每一步中我們都會(huì)繼續(xù)調(diào)用 climbStairs兔跌,climbStairs 這個(gè)函數(shù)模擬爬 1 階和 2 階的情形,并返回兩個(gè)函數(shù)的返回值之和峡蟋。

climbStairs(i,n) = climbStairs(i + 1, n) + climbStairs(i + 2, n)
其中 i 定義了當(dāng)前階數(shù)坟桅,而 n 定義了目標(biāo)階數(shù)。

class Solution {
    public int climbStairs(int n) {
        return climbWays(0, n);
    }
    
    public int climbWays(int curStair, int totalStair){
        if(curStair > totalStair){
            return 0;
        }
        
        if(curStair == totalStair){
            return 1;
        }
        
        return climbWays(curStair +1, totalStair) + climbWays(curStair +2, totalStair);
    }
}
復(fù)雜度分析
  • 時(shí)間復(fù)雜度:O(2n)蕊蝗。樹(shù)形遞歸的大小為 2n仅乓。

在 n=5 時(shí)的遞歸樹(shù)將是這樣的:


  • 空間復(fù)雜度:O(n)。遞歸樹(shù)的深度可以達(dá)到 n 蓬戚。

方法 2:記憶化遞歸

在上一種方法中夸楣,我們計(jì)算每一步的結(jié)果時(shí)出現(xiàn)了冗余。另一種思路是子漩,我們可以把每一步的結(jié)果存儲(chǔ)在 memory 數(shù)組之中豫喧,每當(dāng)函數(shù)再次被調(diào)用,我們就直接從 memory 數(shù)組返回結(jié)果幢泼。

在 memory 數(shù)組的幫助下嘿棘,我們得到了一個(gè)修復(fù)的遞歸樹(shù),其大小減少到 n 旭绒。

public class Solution {
    public int climbStairs(int n) {
        int memo[] = new int[n + 1];
        return climb_Stairs(0, n, memo);
    }
    public int climb_Stairs(int i, int n, int memo[]) {
        if (i > n) {
            return 0;
        }
        if (i == n) {
            return 1;
        }
        if (memo[i] > 0) {
            return memo[i];
        }
        memo[i] = climb_Stairs(i + 1, n, memo) + climb_Stairs(i + 2, n, memo);
        return memo[i];
    }
}
復(fù)雜度分析
  • 時(shí)間復(fù)雜度:O(n) 鸟妙。樹(shù)形遞歸的大小可以達(dá)到 n。
  • 空間復(fù)雜度:O(n) 挥吵。遞歸樹(shù)的深度可以達(dá)到 n重父。

方法 3:動(dòng)態(tài)規(guī)劃

不難發(fā)現(xiàn),這個(gè)問(wèn)題可以被分解為一些包含最優(yōu)子結(jié)構(gòu)的子問(wèn)題忽匈,即它的最優(yōu)解可以從其子問(wèn)題的最優(yōu)解來(lái)有效地構(gòu)建房午,我們可以使用動(dòng)態(tài)規(guī)劃來(lái)解決這一問(wèn)題。

第 ii 階可以由以下兩種方法得到:
在第 (i-1) 階后向上爬 1 階丹允。
在第 (i-2) 階后向上爬 2 階郭厌。

所以到達(dá)第 i 階的方法總數(shù)就是到第 (i?1) 階和第 (i?2) 階的方法數(shù)之和袋倔。

令 dp[i] 表示能到達(dá)第 i 階的方法總數(shù):
dp[i]=dp[i-1]+dp[i-2]

public class Solution {
    public int climbStairs(int n) {
        if (n == 1) {
            return 1;
        }
        int[] dp = new int[n + 1];
        dp[1] = 1;
        dp[2] = 2;
        for (int i = 3; i <= n; i++) {
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[n];
    }
}
復(fù)雜度分析
  • 時(shí)間復(fù)雜度:O(n),單循環(huán)到 n 折柠。
  • 空間復(fù)雜度:O(n)宾娜,dp 數(shù)組用了 n 的空間。

方法 4: 斐波那契數(shù)

在上述方法中扇售,我們使用 dp 數(shù)組前塔,其中 dp[i]=dp[i-1]+dp[i-2]〕斜可以很容易通過(guò)分析得出 dp[i] 其實(shí)就是第 i 個(gè)斐波那契數(shù)华弓。

Fib(n)=Fib(n-1)+Fib(n-2)

現(xiàn)在我們必須找出以 1 和 2 作為第一項(xiàng)和第二項(xiàng)的斐波那契數(shù)列中的第 n 個(gè)數(shù),也就是說(shuō) Fib(1)=1 且 Fib(2)=2困乒。

public class Solution {
    public int climbStairs(int n) {
        if (n == 1) {
            return 1;
        }
        int first = 1;
        int second = 2;
        for (int i = 3; i <= n; i++) {
            int third = first + second;
            first = second;
            second = third;
        }
        return second;
    }
}
復(fù)雜度分析
  • 時(shí)間復(fù)雜度:O(n)寂屏。單循環(huán)到 n,需要計(jì)算第 n 個(gè)斐波那契數(shù)娜搂。
  • 空間復(fù)雜度:O(1)凑保。使用常量級(jí)空間。

方法 5: Binets 方法
算法

這里有一種有趣的解法涌攻,它使用矩陣乘法來(lái)得到第 nn 個(gè)斐波那契數(shù)。矩陣形式如下:
\left[ \begin{matrix} F_{n+1} & F_{n}\\ F_{n} & F_{n-1} \\ \end{matrix} \right] = \left[ \begin{matrix} 1 & 1\\ 1 & 0 \\ \end{matrix} \right]


Q= \left[ \begin{matrix} F_{n+1} & F_{n}\\ F_{n} & F_{n-1}\\ \end{matrix} \right]

按照此方法频伤,第 nn 個(gè)斐波那契數(shù)可以由 Qn-1[0,0] 給出恳谎。

讓我們?cè)囍C明一下。

我們可以使用數(shù)學(xué)歸納法來(lái)證明這一方法憋肖。易知因痛,該矩陣給出了第 3 項(xiàng)(基本情況)的正確結(jié)果。由于 Q^2= \left[ \begin{matrix} 2 & 1\\ 1 & 1\\ \end{matrix} \right]
這證明基本情況是成立的岸更。

假設(shè)此方法適用于查找第 nn 個(gè)斐波那契數(shù)鸵膏,即 Fn=Qn-1[0,0],那么:
Q^{n-1}= \left[ \begin{matrix} F_{n} & F_{n-1}\\ F_{n-1} & F_{n-2}\\ \end{matrix} \right]

現(xiàn)在怎炊,我們需要證明在上述兩個(gè)條件為真的情況下谭企,該方法可以有效找出第 (n+1) 個(gè)斐波那契數(shù),即评肆,F(xiàn)n+1=Qn[0,0]债查。

證明:
Q^{n}= \left[ \begin{matrix} F_{n} & F_{n-1}\\ F_{n-1} & F_{n-2}\\ \end{matrix} \right] \left[ \begin{matrix} 1 & 1\\ 1 & 0\\ \end{matrix} \right] . Q^{n}= \left[ \begin{matrix} F_{n} + F_{n-1} & F_{n}\\ F_{n-1} + F_{n-2} & F_{n-1}\\ \end{matrix} \right] . Q^{n}= \left[ \begin{matrix} F_{n+1} & F_{n}\\ F_{n} & F_{n-1}\\ \end{matrix} \right]

從而, Fn+1=Qn[0,0]瓜挽。得證盹廷。

我們需要為我們的問(wèn)題做的唯一改動(dòng)就是將斐波那契數(shù)列的初始項(xiàng)修改為 2 和 1 來(lái)代替原來(lái)的 1 和 0 【贸龋或者俄占,另一種方法是使用相同的初始矩陣 Q 并使用 result = Qn[0,0] 得出最后結(jié)果管怠。發(fā)生這種情況的原因是我們必須使用原斐波那契數(shù)列的第 2 項(xiàng)和第 3 項(xiàng)作為初始項(xiàng)。

public class Solution {
    public int climbStairs(int n) {
        int[][] q = {{1, 1}, {1, 0}};
        int[][] res = pow(q, n);
        return res[0][0];
    }
    public int[][] pow(int[][] a, int n) {
        int[][] ret = {{1, 0}, {0, 1}};
        while (n > 0) {
            if ((n & 1) == 1) {
                ret = multiply(ret, a);
            }
            n >>= 1;
            a = multiply(a, a);
        }
        return ret;
    }
    public int[][] multiply(int[][] a, int[][] b) {
        int[][] c = new int[2][2];
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 2; j++) {
                c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j];
            }
        }
        return c;
    }
}
復(fù)雜度分析
  • 時(shí)間復(fù)雜度:O(log(n))缸榄。遍歷 log(n) 位渤弛。
  • 空間復(fù)雜度:O(1)。使用常量級(jí)空間碰凶。

方法 6: 斐波那契公式

我們可以使用這一公式來(lái)找出第 n 個(gè)斐波那契數(shù):
F_n = \frac{1}{\sqrt 5} \left[ \begin{matrix} (\frac{1 + \sqrt{5}}{2})^n - (\frac{1-\sqrt{5}}{2})^n\\ \end{matrix} \right]
對(duì)于給定的問(wèn)題暮芭,斐波那契序列將會(huì)被定義為 F0 = 1,F(xiàn)1 = 1欲低,F(xiàn)2= 2辕宏,F(xiàn)n+2= Fn+1 + Fn。嘗試解決這一遞歸公式的標(biāo)準(zhǔn)方法是設(shè)出 Fn 砾莱,其形式為 Fn= an瑞筐。然后,自然有 Fn+1 = an+1和 Fn+2= an+2腊瑟,所以方程可以寫(xiě)作 an+2= an+1+ an聚假。如果我們對(duì)整個(gè)方程進(jìn)行約分,可以得到 a2 = a + 1 或者寫(xiě)成二次方程形式 a2 - a- 1= 0闰非。
對(duì)二次公式求解膘格,我們得到:

a = \frac{1}{\sqrt 5} (\frac{1 \pm \sqrt{5}}{2})

一般解采用以下形式:
F_n = A (\frac{1 + \sqrt{5}}{2})^n +B (\frac{1- \sqrt{5}}{2})^n
n = 0時(shí),有A + B = 1
n = 1時(shí)财松,有 A(\frac{1+ \sqrt{5}}{2}) +B(\frac{1- \sqrt{5}}{2}) = 1

解上述等式瘪贱,我們得到:
A = (\frac{1+\sqrt{5}}{2\sqrt{5}}), B=(\frac{1-\sqrt{5}}{2\sqrt{5}})

將 AA 和 BB 的這些值帶入上述的一般解方程中,可以得到:
F_n = \frac{1}{\sqrt{5}}((\frac{1+\sqrt{5}}{2})^{n+1}-(\frac{1-\sqrt{5}}{2})^{n+1})

public class Solution {
    public int climbStairs(int n) {
        double sqrt5=Math.sqrt(5);
        double fibn=Math.pow((1+sqrt5)/2,n+1)-Math.pow((1-sqrt5)/2,n+1);
        return (int)(fibn/sqrt5);
    }
}
復(fù)雜度分析
  • 時(shí)間復(fù)雜度:O(log(n))辆毡。pow方法將會(huì)用去 log(n) 的時(shí)間菜秦。
  • 空間復(fù)雜度:O(1)。使用常量級(jí)空間舶掖。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末球昨,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子眨攘,更是在濱河造成了極大的恐慌主慰,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鲫售,死亡現(xiàn)場(chǎng)離奇詭異河哑,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)龟虎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)璃谨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事佳吞」俺” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵底扳,是天一觀(guān)的道長(zhǎng)铸抑。 經(jīng)常有香客問(wèn)我,道長(zhǎng)衷模,這世上最難降的妖魔是什么鹊汛? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮阱冶,結(jié)果婚禮上刁憋,老公的妹妹穿的比我還像新娘。我一直安慰自己木蹬,他們只是感情好至耻,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著镊叁,像睡著了一般尘颓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上晦譬,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天疤苹,我揣著相機(jī)與錄音,去河邊找鬼敛腌。 笑死卧土,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的迎瞧。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼逸吵,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼凶硅!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起扫皱,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤足绅,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后韩脑,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體氢妈,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年段多,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了首量。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖加缘,靈堂內(nèi)的尸體忽然破棺而出鸭叙,到底是詐尸還是另有隱情,我是刑警寧澤拣宏,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布沈贝,位于F島的核電站,受9級(jí)特大地震影響勋乾,放射性物質(zhì)發(fā)生泄漏宋下。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一辑莫、第九天 我趴在偏房一處隱蔽的房頂上張望学歧。 院中可真熱鬧,春花似錦摆昧、人聲如沸撩满。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)伺帘。三九已至,卻和暖如春忌锯,著一層夾襖步出監(jiān)牢的瞬間伪嫁,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工偶垮, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留张咳,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓似舵,卻偏偏與公主長(zhǎng)得像脚猾,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子砚哗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

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

  • 接觸DP最早的應(yīng)該就是這道題了吧龙助,翻了翻leetcode submission發(fā)現(xiàn)最早的是在一年前... 而且是最...
    石榴蒂凡尼_21e4閱讀 2,577評(píng)論 0 0
  • 動(dòng)態(tài)規(guī)劃 動(dòng)態(tài)規(guī)劃是一種高性能的牛逼算法,由美國(guó)的R.Bellman提出蛛芥,它是動(dòng)態(tài)就是體現(xiàn)在此算法是基于一個(gè)遞推公...
    董澤平閱讀 1,167評(píng)論 0 12
  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些閱讀 2,029評(píng)論 0 2
  • 看我主頁(yè)簡(jiǎn)介免費(fèi)C++學(xué)習(xí)資源提鸟,視頻教程、職業(yè)規(guī)劃仅淑、面試詳解称勋、學(xué)習(xí)路線(xiàn)、開(kāi)發(fā)工具 每晚8點(diǎn)直播講解C++編程技術(shù)涯竟。...
    編程小世界閱讀 961評(píng)論 0 0
  • 什么是區(qū)塊鏈赡鲜,我想很多人都不明白】昭幔現(xiàn)在走進(jìn)大家視界的就是比特幣,區(qū)塊鏈以后能給大家?guī)?lái)什么變化蝗蛙,在簡(jiǎn)書(shū)看來(lái)就是不停...
    無(wú)畏無(wú)夢(mèng)閱讀 247評(píng)論 0 8