Leetcode 面試題 08.01. 三步問題

Leetcode 面試題 08.01. 三步問題

1、問題分析

題目鏈接:https://leetcode-cn.com/problems/three-steps-problem-lcci/
  可以使用動態規劃解決,狀態轉移方程是:dp[i] = dp[i-1] + dp[i-2] + dp[i-3],最重要的還是數據太大,導致的溢出問題。代碼我已經進行了詳細的註釋,理解應該沒有問題,讀者可以作爲參考,如果看不懂(可以多看幾遍),歡迎留言哦!我看到會解答一下。

2、問題解決

  筆者以C++方式解決。

#include "iostream"

using namespace std;

#include "algorithm"
#include "vector"
#include "queue"
#include "set"
#include "map"
#include "cstring"
#include "stack"

class Solution {
private:
    // 定義最大樓梯個數
    const static int MAXN = 1000001;
    // dp[i] 代表 i 階樓梯有多少種走法,初始化爲0
    // dp[i] = dp[i-1] + dp[i-2] + dp[i-3]
    // 也就是最後一步走 1 步,或2步或3步的和
    int dp[MAXN] = {0};
public:
    int waysToStep(int n) {
        int i = init(n);
        return i;
    }

    /**
     * 獲取第 index 階樓梯有多少種走法
     * @param index
     * @return
     */
    int init(int index) {

        if (index <= 0) {
            return 0;
        }
        // 如果前面計算出了結果,直接返回
        if (dp[index] != 0) {
            return dp[index];
        }
        // 遞歸邊界
        if (index == 1) {
            dp[index] = 1;
            return dp[index];
        }
        if (index == 2) {
            dp[index] = 2;
            return dp[index];
        }
        if (index == 3) {
            dp[index] = 4;
            return dp[index];
        }

        //取模,對兩個較大的數之和取模再對整體取模,防止越界(這裏也是有講究的)
        //假如對三個dp[i-n]都 % 1000000007,那麼也是會出現越界情況(導致溢出變爲負數的問題)
        //因爲如果本來三個dp[i-n]都接近 1000000007 那麼取模後仍然不變,但三個相加則溢出
        //但對兩個較大的dp[i-n]:dp[i-2],dp[i-3]之和mod 1000000007,那麼這兩個較大的數相加大於 1000000007但又不溢出
        //取模後變成一個很小的數,與dp[i-1]相加也不溢出
        //所以取模操作也需要仔細分析
        // ------------------------------------上面是參考 LeetCode題解的 -------------------------------
        // 下面說說我遇到的問題,我剛剛開始想,反正數很大是吧,那就霸王硬上弓,我直接來個 unsigned long long 不就可以了,還是 too young too simple
        // unsigned long long 還是會越界,但是不會報溢出異常,如果溢出了,就相當於取模2^64了。望後來的人少踩坑
        dp[index] = ((init(index - 1) + init(index - 2)) % 1000000007 + init(index - 3)) % 1000000007;

        return dp[index];
    }
};

int main() {
    int n = 76;
    Solution *pSolution = new Solution;
    int i = pSolution->waysToStep(n);
    cout << i << endl;
    system("pause");
    return 0;
}

運行結果

在這裏插入圖片描述

有點菜,有時間再優化一下。

3、總結

  書上的代碼直接運行絕大部分是對的,但是總有一些軟件的更新使得作者無能爲力。之前的API是對的,但是之後就廢棄了或修改了是常有的事。所以我們需要跟蹤源代碼。這只是一個小小的問題,如果沒有前輩的無私奉獻,很難想象我們自己一天能學到多少內容。感謝各位前輩的辛勤付出,讓我們少走了很多的彎路!

點個贊再走唄!歡迎留言哦!

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