《劍指offer》 遞迴和迴圈

2021-09-12 10:39:44 字數 1730 閱讀 2744

記錄一下牛客網上,劍指 offer 分割槽的考點為「遞迴和迴圈」的題,都很簡單,共 4 題:

1、斐波那契數列

2、跳台階

3、**跳台階

4、矩形覆蓋

1、斐波那契數列

int

fibonacci

(int n)

return b;

}

遞迴方式(很容易想到),但是ac不了,因為遞迴次數過多,棧溢位了:

int

fibonacci

(int n)

從下邊這張圖就可以看出,計算fibonacci(6)就需要計算很多次,比如 f(2) 就計算了 5 次。

如果要用遞迴的方式計算 fibonacci 數列的話,需要使用尾遞迴。如果在遞迴函式中,遞迴呼叫返回的結果總被直接返回,則稱為尾部遞迴。尾部遞迴的函式有助將演算法轉化成函式程式語言,而且從編譯器角度來說,亦容易優化成為普通迴圈。這是因為從電腦的基本面來說,所有的迴圈都是利用重複移跳到**的開頭來實現的。如果有尾部歸遞,就只需要疊套乙個堆疊,因為電腦只需要將函式的引數改變再重新呼叫一次。

int

fibonacci

(const

int& n,

const

int& a,

const

int& b)

intfibonacci

(int n)

2、跳台階
int

jumpfloor

(int number)

return b;

}

3、**跳台階

一開始的想法就是,跳到第n階台階的方法是跳到前邊 n-1 個台階的方法總數+1(因為可以直接跳到第n階)。ac**如下:

int

jumpfloorii

(int number)

但是可以推倒,記 cur 之前所有的總和是 prev,那麼跳到 cur 這個位置的方法就是 prev+1(比如叫 a),然後 prev 就變成了 prev + prev + 1,也就是 2 * prev + 1,然後再向後跳到 cur + 1就是 prev 再 + 1,也就是 cur+1 位置的方法是 2 * prev + 2,而 a 是 prev+1,那麼就是每次跳的方法是是上一屆台階的一倍,也就是 2*a。

其實最簡單的想法就是,既然每階台階我都可以選擇跳還是不跳,而只有最後乙個台階是必須跳的,那不就是 2 的 (n - 1) 地方麼。ac**如下:

int

jumpfloorii

(int number)

4、矩形覆蓋

我們可以用21的小矩形橫著或者豎著去覆蓋更大的矩形。請問用n個21的小矩形無重疊地覆蓋乙個2n的大矩形,總共有多少種方法?

因為大矩形是 2n 大小的,那麼就只有兩種方法,豎著放乙個,或者橫著放倆,也就是 f(n) = f(n - 1) +f(n - 2),這不還是斐波那契數列麼。

int

rectcover

(int number)

return b;

}

劍指offer 遞迴和迴圈

遞迴雖然比較簡潔,但他同時也有顯著的缺點。遞迴由於是函式呼叫自身,而函式呼叫是有時間和空間的消耗的,每一次函式呼叫都需要在記憶體棧中分配空間以儲存引數 返回位址及臨時變數,而且往棧裡壓入資料和彈出資料都需要時間。1 斐波那契數列 0,1,1,2,3,5,8,13 遞迴 缺陷 重複計算的太多 int ...

劍指offer 遞迴和迴圈

問題描述 大家都知道斐波那契數列,現在要求輸入乙個整數 n,請你輸出斐波那契數列的第 n 項 從 0 開始,第 0 項為 0 n 39 方法一 function fibonacci n var arr 0,1 for var i 2 i n i return arr n 方法二 function f...

劍指offer 迴圈遞迴

class solution return res 乙隻青蛙一次可以跳上1級台階,也可以跳上2級。求該青蛙跳上乙個n級的台階總共有多少種跳法。class solution return res 乙隻青蛙一次可以跳上1級台階,也可以跳上2級 它也可以跳上n級。求該青蛙跳上乙個n級的台階總共有多少種跳法...