遞歸調用2

問題:我們可以用2*1的小矩形橫着或者豎着去覆蓋更大的矩形。請問用n個2*1的小矩形無重疊地覆蓋一個2*n的大矩形,總共有多少種方法?
思路:剛開始想的是和前面提到的青蛙跳的想法差不多,因爲矩形可以橫着放,也可以豎着放,對n從1開始區分情況:
不嚴格的說橫着放和豎着放有時候是一種情況,也就是說
這裏寫圖片描述
這裏(1)和(2)是兩種方法,而不是說(1)旋轉後就和(2)一樣了。
n=1時,有1种放置方法;
n=2時,有2种放置方法;
n=3時,有3中放置方法;
。。。
這樣就得到了f(n)=f(n-1)+f(n-2),還是一個斐波拉契數列。
遇到的一個問題,按照之前的做法寫了下面一段代碼:

class Solution {
public:
    int rectCover(int number) {
        if (number < 0)
            cout << "ERROR!" << endl;
        if (number == 1)
            return 1;
        if (number == 2)
            return 2;
        else
            return rectCover(number-1)+rectCover(number-2);
    }
};

在測試的時候出現段錯誤,堆棧溢出。想想應該是遞歸調用層數太多引起的。我們知道在進行遞歸調用的時候,會先把當前的環境,變量都壓入一個棧中保存起來,等到運行完畢後再從棧中取出原來的東西,繼續往下操作。當遞歸操作太多的時候,可能會由於內存大小的限製造成一些錯誤的產生。改用如下的程序來求問題的解:

class Solution {
public:
    int rectCover(int number) {
        int value0 = 0, value1 = 1;
        int temp;
        while (number-- > 0) {
            temp = value1;
            value1 += value0;
            value0 = temp;
        }
        return value1;
    }
};

這個同樣也是求的一個斐波拉契數列的最後一項的值,也就是本問題的解。
關於遞歸的很多問題還是有很多需要去理解。包括遞歸的層數的問題,遞歸的優缺點,遞歸對內存的需求影響,在遞歸中何時保存何值的問題等等。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章