课程规划会分为四个阶段进行:
1.题目解析
2.讲解算法原理(动态规划的原理)
3.编写代码
4.空间优化
1. 第 N 个泰波那契数(easy)
泰波那契数相当于斐波那契数的孪生兄弟,是它的加强版。
1.题目解析
2.讲解算法原理
如果用动态规划的原理来解决这个问题的话,一般分五步进行
(1) 确定状态表示
动态规划的做题流程一般是先定义一个dp表,dp表一般就是一个一维数组或者是一个二维数组
先定义一个数组,这个数组一般就叫做dp表,然后想办法把这个dp表填满,填满之后里面的某一个值可能就是我们的最终结果。
状态表示就是dp表中某一个值所代表的含义
状态表示是怎么来的呢?
1,题目要求
2,经验 + 题目要求
3,分析问题的过程中,发现重复子问题,把重复子问题抽象成为状态表示
所以刚开始先练前两个,等到动态规划熟了,进而介绍第三种,第三种就是表示动态规划的方式。
(2)根据状态表示来推导状态转移方程
和(1)一样,不用学术型的语言来表示状态转移方程,我们这里的状态转移方程就是dp[i]等于什么。
(1)和(2)是动态规划中最核心的两步
(3)初始化
初始化的含义就是保证填表的时候不越界。
怎么填表?就是根据状态转移方程来进行填表。
(4)填表顺序
为什么要研究它呢?就是为了填写当前状态的时候,所需要的状态已经计算过了
(5)返回值
返回值就是最终我们想要的结果。结合题目要求 + 状态表示
3.编写代码
动态规划代码的编写是非常固定的四步
1,创建一个dp表
2,在正式的填表之前初始化
3,正式填表
4,确定返回值
因为有n个值,所以要创建一个n + 1的dp表,才能访问到第 n 个值,因为数组的下标是从0开始的。
解题代码:
class Solution {
public:
int tribonacci(int n) {
//处理一下边界问题
if (n == 0 || n == 1)
return n;
if (n == 2)
return 1;
vector<int> a(n + 1);
a[0] = 0, a[1] = a[2] = 1;
for (int i = 3; i <= n; i++)
a[i] = a[i - 1] + a[i - 2] + a[i - 3];
return a[n];
}
}
4.空间优化
关于动态规划空间的优化,一般都用滚动数组。
滚动数组一般用有限个变量来表示的。为了取名方便就给它们起名叫滚动数组。用滚动数组做优化的时候,一定要确定好顺序。 赋值操作一定要确保从前向后赋值。
//滚动数组的写法
class Solution {
public:
int tribonacci(int n) {
// 处理一下边界问题
if (n == 0 || n == 1)
return n;
if (n == 2)
return 1;
int a = 0, b = 1, c = 1, d = 0;
for (int i = 3; i <= n; i++) {
d = a + b + c;
a = b, b = c, c = d;
}
return d;
}
};
2. 三步问题(easy)
1.题目解析
当小孩在第0格位置的时候,要去第一节台阶,只有1种走法,要想到第二节台阶,可以从第一节台阶走,去第一节的台阶有一种走法,从1到2有一种,也可以从0阶台阶直接到第二节这算一种走法,加起来有两种走法,到第三节的时候,可以从0到3,也可以从1到三,也可以2到3,再加上如何到1、2台阶的方法数,加起来有四种......
2.讲解算法原理
(1) 确定状态表示
dp[i]表示到达 i 位置时,一共有多少种方法。
(2)根据状态表示来推导状态转移方程
以 i 位置的状态,最近的一步来划分问题,dp[i]可以分为三种情况,要么从dp[i - 1]到达dp[i],要么从dp[i - 2]到达dp[i],要么从dp[i - 3]到达dp[i]。
那么状态转移方程就有了:dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3]
(3)初始化
dp[0] = 0,dp[1] = 1,dp[2] = 2,dp[3] = 4
(4)填表顺序
从左到右
(5)返回值
1,创建dp表
2,初始化
3,填表
4,确定返回值
//题解
class Solution {
public:
int waysToStep(int n) {
const int MOD = 1e9 + 7;
if (n == 0 || n == 1 || n == 2)
return n;
if (n == 3)
return 4;
vector<int> dp(n + 1);
dp[1] = 1, dp[2] = 2, dp[3] = 4;
for (int i = 4; i <= n; i++) {
//因为值很大,所以要对结果取模1e9 + 7
dp[i] = ((dp[i - 1] + dp[i - 2]) % MOD + dp[i - 3]) % MOD;
}
return dp[n];
}
};