記錄一下牛客網上,劍指 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級的台階總共有多少種跳法...