当前位置:   article > 正文

18.动态规划之斐波那契数列模型1

18.动态规划之斐波那契数列模型1

1.第N个斐波那契数

1137. 第 N 个泰波那契数 - 力扣(LeetCode)

做题流程 

1. 状态表示:

这道题可以【根据题目的要求】直接定义出状态表示:
dp[i] 表示:第 i 个泰波那契数的值。

2. 状态转移方程:

题目已经非常贴心的告诉我们了:
dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3]

3. 初始化:

从我们的递推公式可以看出, dp[i] i = 0 以及 i = 1 的时候是没有办法进⾏推导的,因
dp[-2] dp[-1] 不是⼀个有效的数据。
因此我们需要在填表之前,将 0, 1, 2 位置的值初始化。题⽬中已经告诉我们 dp[0] = 0,
dp[1] = dp[2] = 1

4. 填表顺序:

毫⽆疑问是「从左往右」。

5. 返回值:

应该返回 dp[n] 的值。
  1. class Solution {
  2. public int tribonacci(int n) {
  3. // 1. 创建 dp 表
  4. // 2. 初始化
  5. // 3. 填表
  6. // 4. 返回结果
  7. // 处理边界情况
  8. if (n == 0)
  9. return 0;
  10. if (n == 1 || n == 2)
  11. return 1;
  12. int[] dp = new int[n + 1];
  13. dp[0] = 0;
  14. dp[1] = dp[2] = 1;
  15. for (int i = 3; i <= n; i++)
  16. dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3];
  17. return dp[n];
  18. }
  19. }

空间优化

  1. class Solution {
  2. public int tribonacci(int n) {
  3. if (n == 0)
  4. return 0;
  5. if (n == 1 || n == 2)
  6. return 1;
  7. int a = 0, b = 1, c = 1, d = 0;
  8. for (int i = 3; i <= n; i++) {
  9. d = a + b + c;
  10. a = b;
  11. b = c;
  12. c = d;
  13. }
  14. return d;
  15. }
  16. }

2.三步问题 

面试题 08.01. 三步问题 - 力扣(LeetCode)

算法思路

1. 状态表示

这道题可以根据「经验 + 题⽬要求」直接定义出状态表⽰:
dp[i] 表⽰:到达 i 位置时,⼀共有多少种⽅法。

2. 状态转移⽅程

以 i 位置状态的最近的⼀步,来分情况讨论:
如果 dp[i] 表⽰⼩孩上第 i 阶楼梯的所有⽅式,那么它应该等于所有上⼀步的⽅式之和:
i. 上⼀步上⼀级台阶, dp[i] += dp[i - 1]
ii. 上⼀步上两级台阶, dp[i] += dp[i - 2]
iii. 上⼀步上三级台阶, dp[i] += dp[i - 3]
综上所述, dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3]
需要注意的是,这道题⽬说,由于结果可能很⼤,需要对结果取模。
在计算的时候,三个值全部加起来再取模,即 (dp[i - 1] + dp[i - 2] + dp[i - 3])
% MOD 是不可取的,同学们可以试验⼀下, n 取题⽬范围内最⼤值时,⽹站会报错 signed
integer overflow
对于这类需要取模的问题,我们每计算⼀次(两个数相加/乘等),都需要取⼀次模。否则,万⼀
发⽣了溢出,我们的答案就错了。

3. 初始化

从我们的递推公式可以看出, dp[i] i = 0, i = 1 以及 i = 2 的时候是没有办法进⾏
推导的,因为 dp[-3] dp[-2] dp[-1] 不是⼀个有效的数据。
因此我们需要在填表之前,将 1, 2, 3 位置的值初始化。
根据题意, dp[1] = 1, dp[2] = 2, dp[3] = 4

4. 填表顺序

毫⽆疑问是「从左往右」。

5. 返回值

应该返回 dp[n] 的值。
  1. class Solution {
  2. public int waysToStep(int n) {
  3. // 1. 创建 dp 表
  4. // 2. 初始化
  5. // 3. 填表
  6. // 4. 返回值
  7. int MOD = (int) 1e9 + 7;
  8. // 处理⼀下边界情况
  9. if (n == 1 || n == 2)
  10. return n;
  11. if (n == 3)
  12. return 4;
  13. int[] dp = new int[n + 1];
  14. dp[1] = 1;
  15. dp[2] = 2;
  16. dp[3] = 4;
  17. for (int i = 4; i <= n; i++)
  18. dp[i] = ((dp[i - 1] + dp[i - 2]) % MOD + dp[i - 3]) % MOD;
  19. return dp[n];
  20. }
  21. }

3.最小花费爬楼梯

746. 使用最小花费爬楼梯 - 力扣(LeetCode)

题目解析

算法思路 

解法一:

  1. class Solution {
  2. public int minCostClimbingStairs(int[] cost) {
  3. // 1. 创建 dp 表
  4. // 2. 初始化
  5. // 3. 填表
  6. // 4. 返回值
  7. int n = cost.length;
  8. int[] dp = new int[n + 1];
  9. for (int i = 2; i <= n; i++)
  10. dp[i] = Math.min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
  11. return dp[n];
  12. }
  13. }

解法二:

  1. class Solution {
  2. public int minCostClimbingStairs(int[] cost) {
  3. // 1. 创建 dp 表
  4. // 2. 初始化
  5. // 3. 填表
  6. // 4. 返回值
  7. int n = cost.length;
  8. int[] dp = new int[n];
  9. dp[n - 1] = cost[n - 1];
  10. dp[n - 2] = cost[n - 2];
  11. for (int i = n - 3; i >= 0; i--)
  12. dp[i] = Math.min(dp[i + 1], dp[i + 2]) + cost[i];
  13. return Math.min(dp[0], dp[1]);
  14. }
  15. }

 4.解码方法

91. 解码方法 - 力扣(LeetCode)

算法思路 

  1. class Solution {
  2. public int numDecodings(String ss) {
  3. // 1. 创建 dp 表
  4. // 2. 初始化
  5. // 3. 填表
  6. // 4. 返回值
  7. int n = ss.length();
  8. char[] s = ss.toCharArray();
  9. int[] dp = new int[n];
  10. if (s[0] != '0')
  11. dp[0] = 1; // 初始化第⼀个位置
  12. if (n == 1)
  13. return dp[0]; // 处理边界情况
  14. // 初始化第⼆个位置
  15. if (s[1] != '0' && s[0] != '0')
  16. dp[1] += 1;
  17. int t = (s[0] - '0') * 10 + s[1] - '0';
  18. if (t >= 10 && t <= 26)
  19. dp[1] += 1;
  20. for (int i = 2; i < n; i++) {
  21. // 先处理第⼀种情况
  22. if (s[i] != '0')
  23. dp[i] += dp[i - 1];
  24. // 处理第⼆种情况
  25. int tt = (s[i - 1] - '0') * 10 + s[i] - '0';
  26. if (tt >= 10 && tt <= 26)
  27. dp[i] += dp[i - 2];
  28. }
  29. return dp[n - 1];
  30. }
  31. }

 细节问题

  1. ass Solution {
  2. public int numDecodings(String ss) {
  3. // 1. 创建 dp 表
  4. // 2. 初始化
  5. // 3. 填表
  6. // 4. 返回值
  7. int n = ss.length();
  8. char[] s = ss.toCharArray();
  9. int[] dp = new int[n + 1];
  10. dp[0] = 1; // 保证后续填表是正确的
  11. if (s[1 - 1] != '0')
  12. dp[1] = 1;
  13. for (int i = 2; i <= n; i++) {
  14. // 先处理第⼀种情况
  15. if (s[i - 1] != '0')
  16. dp[i] += dp[i - 1];
  17. // 处理第⼆种情况
  18. int tt = (s[i - 2] - '0') * 10 + s[i - 1] - '0';
  19. if (tt >= 10 && tt <= 26)
  20. dp[i] += dp[i - 2];
  21. }
  22. return dp[n];
  23. }
  24. }

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号