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是对的,但是之后就废弃了或修改了是常有的事。所以我们需要跟踪源代码。这只是一个小小的问题,如果没有前辈的无私奉献,很难想象我们自己一天能学到多少内容。感谢各位前辈的辛勤付出,让我们少走了很多的弯路!

点个赞再走呗!欢迎留言哦!

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