【每天一題】劍指 Offer 10- II. 青蛙跳臺階問題

一隻青蛙一次可以跳上1級臺階,也可以跳上2級臺階。求該青蛙跳上一個 n 級的臺階總共有多少種跳法。
答案需要取模 1e9+7(1000000007),如計算初始結果爲:1000000008,請返回 1。

示例 1:
輸入:n = 2
輸出:2
示例 2:

輸入:n = 7
輸出:21

思路分析,拿到本題,隨便舉幾個數找規律,發現符合斐波那契數列。
那直接跟上一篇文章一樣,代碼大致差不多
這裏要注意的是,n=0的時候,是一次,n=1的時候是一次,所以和斐波那契數列數列還有一點差距,差了一位

class Solution {
    public int numWays(int n) {
        int a = 0, b = 1, sum;
        for(int i = 0; i < n; i++){
            sum = (a + b) % 1000000007;
            a = b;
            b = sum;
        }
        return b;
    }
}

PS : 爲什麼要模1000000007(一,八個零,七)
大數相乘,大數的排列組合等爲什麼要取模
1000000007是一個質數(素數),對質數取餘能最大程度避免結果衝突/重複
int32位的最大值爲2147483647,所以對於int32位來說1000000007足夠大。
int64位的最大值爲2^63-1,用最大值模1000000007的結果求平方,不會在int64中溢出。
所以在大數相乘問題中,因爲(a∗b)%c=((a%c)∗(b%c))%c,所以相乘時兩邊都對1000000007取模,再保存在int64裏面不會溢出。
這道題爲什麼要取模,取模前後的值不就變了嗎?
確實:取模前 f(43) = 701408733, f(44) = 1134903170, f(45) = 1836311903, 但是 f(46) > 2147483647結果就溢出了。

_____,取模後 f(43) = 701408733, f(44) = 134903163 , f(45) = 836311896, f(46) = 971215059沒有溢出。

取模之後能夠計算更多的情況,如 f(46)

這道題的測試答案與取模後的結果一致。

總結一下,這道題要模1000000007的根本原因是標準答案模了1000000007。不過大數情況下爲了防止溢出,模1000000007是通用做法,原因見第一點。
還有一題類似的

假設你正在爬樓梯。需要 n 階你才能到達樓頂。
每次你可以爬 1 或 2 個臺階。你有多少種不同的方法可以爬到樓頂呢?
注意:給定 n 是一個正整數。

示例 1:
輸入: 2
輸出: 2
解釋: 有兩種方法可以爬到樓頂。
1.  1 階 + 1 階
2.  2 階
示例 2:

輸入: 3
輸出: 3
解釋: 有三種方法可以爬到樓頂。
1.  1 階 + 1 階 + 1 階
2.  1 階 + 2 階
3.  2 階 + 1 階

兩題類似,但是有一個地方不一樣,這個答案不需要取模 1e9+7(1000000007)。

class Solution {
    public int climbStairs(int n) {
       int a = 0, b = 1, sum;
        for(int i = 0; i < n; i++){
            sum = a + b);
            a = b;
            b = sum;
        }
        return b;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章