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是對的,但是之後就廢棄了或修改了是常有的事。所以我們需要跟蹤源代碼。這只是一個小小的問題,如果沒有前輩的無私奉獻,很難想象我們自己一天能學到多少內容。感謝各位前輩的辛勤付出,讓我們少走了很多的彎路!
點個贊再走唄!歡迎留言哦!