昨天晚上睡前看了一下問題描述,講的是乙隻青蛙跳n個台階,一次可以跳一階,一次也可以跳兩階,問一共有多少種跳法。
當時我的思路是:
先想了n=1和n=2的情況,
當n=1時,只有一種跳法--即1;
當n=2時,有兩種跳--1 1或者2
因為小青蛙一次可以跳1或者2,
所以我想把n=1和n=2的情況作為遞迴出口。
比如,n=3的情況,就相當於小青蛙跳了乙個2,和乙個1
並且他們之間是可以有順序的,
一共兩種順序:
小青蛙先跳乙個n=1,再跳乙個n=2;
小青蛙先跳乙個n=2,再跳乙個n=1。
然而,問題出現了,當小青蛙跳n=2時,選擇了1 1跳法,
那麼此時上述兩種順序跳出來的結果都是1 1 1,
說明有重複。
當n取更大的時候,這種重複更多,我們需要把它減去。
想到這的時候,我就知道,我的想法肯定錯了。
遞迴演算法是為了讓人好理解,犧牲一部分機器的執行時間,來換取程式的更強可讀性。
我這想法已經把自己繞進去了,顯然是不可行的。
下面一起來學一學這個問題吧!
【一、思路 中會闡述清楚為什麼不會出現重複問題】
乙隻青蛙一次可以跳上1級台階,也可以跳上2級台階。求該青蛙跳上乙個n級的台階總共有多少種跳法?當n=1時,一共有一種跳法(1)
當n=2時,一共有兩種跳法(1,1),(2)
當n>2時,
這裡我們以n=3為例:
由於很好列舉,我們直接給出跳法,
一共3種:
(1,1,1)
(1,2)
(2,1)
如果我們去掉跳的第一次,
如(1,1,1)一共跳了3次,去掉第一次跳的1階,剩下的結果為(1,1)
同理,剩下兩種跳法去掉第一次後的結果分別為(2)和(1)。
我們把他們放在一起看一下:
(1,1)
(2)(1)
再觀察:這前兩種:(1,1)和(2)不正好是n=2時的跳法嗎?
最後一種,也正好是n=1的跳法。
我們再來列舉一下n=4的情況:
(1,1,1,1)
(1,1,2)
(1,2,1)
(2,1,1)
(2,2)
一共五種。
以第一步跳的是1還是2,我們來划上分割線:
(1,1,1,1)
(1,1,2)
(1,2,1)
------分割線-----------上為a段,下為b段
(2,1,1)
(2,2)
然後,我們對a段進行去掉第一步的處理:
(1,1,1)
(1,2)
(2,1)
是n=3的情景。
同理,對b段進行去掉第一步的處理:
(1,1)
(2)是n=2的情景。
n=4可以劃分為n=3和n=2兩個子問題,而n=3又可以劃分為n=2和n=1兩個子問題,
也就是說,n=4 --> n=3 + n=2 --> n=2 + n=1 + n=2
而n=1和n=2就是我們的初始條件,遞迴出口,
所以完成了遞迴。
本題和斐波那契數列有異曲同工之妙。
回過頭來,我們再想想一開始我的想法出現的問題:是否會導致重複?
答案是不會的。
因為我們是以第一步是1還是2來劃分子問題,這裡的2是一次跳兩階,很明顯,第一步已經不一樣了,所以不會出現重複的問題。
用概率論的思想就是先分類
分第一步跳1次還是2次兩大類
分類用加法;
而對於第一步跳一次的情景,
它又和後面的步驟形成了分步執行問題
分步用乘法。
但是它自身就只有一步,
所以相當於是
這裡我們就把是否會出現重複問題給講清楚了。
int frog_jump(int n)
int main()
本樣例**程式執行結果為8,
測試多組樣例,滿足題意。
C語言入門筆記 第五講 迴圈語句之for
for迴圈是用的最多的迴圈,其次是while,最後是do while。for 表示式1 表示式2 表示式3 迴圈語句 表示式1表示式1為初始化部分,用於初始化迴圈變數的。表示式2表示式2為條件判斷部分,用於判斷 迴圈時候終止。表示式3表示式3為調整部分,用於迴圈條件的調整。我們來看乙個例子 使用fo...
C語言入門筆記 第五講 迴圈語句之while
我們已經掌握了,if語句。當條件滿足的情況下,if語句後的語句執行,否則不執行。但是這個語句只會執行一次。但是我們發現生活中很多的實際的例子是 同一件事情我們需要完成很多次。那我們怎麼做呢?c語言中給我們引入了 while,for,do while 三種語句,可以實現迴圈。while 語法結構 wh...
嵌入式c 軟體開發筆記 第六講
對檔案進行讀寫操作 讀檔案operator int get istream get int istream get char int n,char deli istream getline char int n get vs getline get 和getline 最大的區別就是,get 遇到界定...