采用动态规划,一般分五步:
Tn
等于前三项之和
dp[i] = dp[i-1]+dp[i-2]+dp[i-3]
dp[i]
依赖的是前三个状态dp[0]=0 dp[1]=dp[2]=1
从左向右
dp[n]
/**
* 2024-8-3 * 1. 求第 N 个泰波那契数
* @param n
* @return
*/
public int tribonacci(int n) {
//1. 创建 dp表
int[] dp = new int[n + 1];
//处理一下边界情况
if (n == 0) return 0;
if (n == 1 || n == 2) return 1;
//2. 初始化
dp[0] = 0;
dp[1] = dp[2] = 1;
//3. 填表
for (int i = 3; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3];
}
//4. 返回值
return dp[n];
}
注意:
for
循环的起点是 i == 3
i = n
滚动数组 当在填 dp 表的时候,每次计算只需要前三个值,再前面的值都没用,所占的空间也就浪费了,这时候就可以用滚动数组
/**
* 利用滚动数组
* 进行空间优化
*
* @param n
* @return
*/
public int tribonacci2(int n) {
//处理一下边界情况
if (n == 0) return 0;
if (n == 1 || 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;
}
除了上面的两个点之外,注意:
dp[i]
代表上到第 i
阶共有多少种方法
dp[i] = dp[i-1]] + dp[i-2] +dp[i-3]
i
位置状态,最近的一步,来划分问题dp[i]
dp[i-1]
种dp[i-2]
种dp[i-3]
种dp[1] = 1; dp[2] = 2; dp[3] = 4;
dp[n]
public int waysToStep(int n) {
int MOD = (int)1e9 + 7;
//处理边界情况
if(n == 1 || n == 2) return n;
if(n == 3) return 4;
int[] dp = new int[n+1];
dp[1] = 1; dp[2] = 2; dp[3] = 4;
for (int i = 4; i <= n; i++) {
dp[i] = ((dp[i-1] + dp[i-2]) % MOD + dp[i-3]) % MOD;
}
return dp[n];
}
注意:
首先需要找到楼顶在哪,在数组最后一个元素的下一位
当走到最后一个元素的下一位才算走到终点,走到最后一个元素不算
i
位置为结尾dp[i]
表示到达 i
位置时的最小花费dp[i]
的状态
dp[i-1]
、dp[i-2]
…dp[i+1]
、dp[i+2]
…i-1
位置,然后支付 cost[i-1]
,走一步到达 i 位置==> dp[i-1] + cost[i-1]
i-2
位置,然后支付 cost[i-2]
,走两步到达 i 位置==> dp[i-2] + cost[i-2]
dp[i] = min((dp[i-1] + cost[i-1]), (dp[i-2] + cost[i-2]))
dp[n]
就是换了一种状态表示
i
位置为起点dp[i]
表示从 i
出发,到达楼顶的最小花费cost[i]
之后,往后走一步,从 i+1
的位置出发,到达终点==> cost[i] + dp[i+1]
cost[i]
之后,往后走两步,从 i+2
的位置出发,到达终点==> cost[i] + dp[i+2]
dp[i] = min ((cost[i] + dp[i+1]), cost[i] + dp[i+2])
i+1
和 i+2
位置的值,所以我们应该先初始化后面的值dp[n-1] = cost[n-1]
dp[n-2] = cost[n-2]
min(dp[0], dp[1])
解法一:
public int minCostClimbingStairs(int[] cost) {
int n = cost.length;
int[] dp = new int[n+1];
for (int i = 2; i <= n; i++) {
dp[i] = Math.min((dp[i - 1] + cost[i - 1]),
(dp[i - 2] + cost[i - 2]));
}
return dp[n];
}
解法二:
public int minCostClimbingStairs2(int[] cost) {
int n = cost.length;
int[] dp = new int[n];
dp[n-1] = cost[n-1];
dp[n-2] = cost[n-2];
for (int i = n-3; i >= 0; i--) {
dp[i] = Math.min(dp[i+1], dp[i+2]) + cost[i];
}
return Math.min(dp[0],dp[1]);
}