F(n) = F(n - 1) + F(n - 2),其中 n > 1
示例:
输入:n = 2
输出:1
解释:F(2) = F(1) + F(0) = 1 + 0 = 1
做题步骤:
还记得我们第一步需要怎么来分析的吗?
第一步我们需要确定这题的 DP 数组该怎么去创建?
第二步需要我们推导出本题的 DP 公式。
第三步进行循环得到我们需要的结果。
思路:
通过做题步骤我们能知道这个 DP数组 的长度是 n + 1
(因为需要从0开始到n,所以长度也就是 n + 1
)
题目所说从 1 后面开始每一项的数字都是前两项的和。通过解析这句话我们能知道我们的 循环是从2开始,到n结束 。而推导公式则就是:
dp[i] = dp[i - 1] + dp[i - 2]
当我们完成上述的步骤时接下来就是将这题给实现了。
代码:
Python版本:
class Solution:
def fib(self, n: int) -> int:
if n < 2:
return n
dp = [0]* (n + 1)
dp[1] = 1
for i in range(2 , n + 1):
dp[i] = dp[i - 1] + dp[i - 2]
return dp[n]
Java版本:
class Solution {
public int fib(int n) {
if (n == 0) return 0;
if (n == 1) return 1;
int[] dp = new int[n + 1];
dp[1] = 1;
for (int i = 2; i < n + 1; i++){
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}
}
我们做了一个比较简单的DP题,那我们再来看另外一个简单的DP问题吧
题目:
给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。
你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。
请你计算并返回达到楼梯顶部的最低花费。
示例:
输入:cost = [10,15,20]
输出:15
解释:你将从下标为 1 的台阶开始。
- 支付 15 ,向上爬两个台阶,到达楼梯顶部。
总花费为 15
做题步骤:
DP数组 的创建。
推导出本题的 DP 公式。
进行循环。
思路:
在题目的含义中我们已经知道了 用最小的花费来达到顶楼! 则我们需要创建的 DP数组 长度就为 n + 1
(第n
个下标代表的是楼顶)。则也能得到动态规划的公式和循环的开始点和结束点!
动态规划公式:
dp[i] = min(dp[i-1]+cost[i-1],cost[i-2]+dp[i-2])//从4开始的循环公式
dp[i] = min(dp[i - 1] + cost[i - 1], cost[i - 2] )//当i是等于3的时候判断方程式
dp[i] = min(cost[i - 1], cost[i - 2])//等于2的时候的一个公式
代码:
Python版本
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
dp = [0 for i in range(len(cost)+1)]
for i in range(2,len(cost)+1):
if i ==3 :
dp[i] = min(dp[i - 1] + cost[i - 1], cost[i - 2] )
elif i ==2 :
dp[i] = min(cost[i - 1], cost[i - 2])
else:
dp[i] = min(dp[i-1]+cost[i-1],cost[i-2]+dp[i-2])
return dp[len(cost)]
Java版本:
class Solution {
public int minCostClimbingStairs(int[] cost) {
int[] dp = new int[cost.length + 1];
for(int i = 2; i < cost.length + 1; i ++){
if (i == 2){
dp[i] = Math.min(cost[i - 1], cost[i - 2]);
}
else if (i == 3){
dp [i] = Math.min(cost[i - 2] , dp[i - 1] + cost[i - 1]);
}else{
dp[i] = Math.min(cost[i - 1] + dp[i - 1] , cost[i - 2] + dp[i - 2]);
}
}
return dp[cost.length];
}
}
OK,例题看完了,接下来就是来看习题了哦!!!
模块练习题
| 题目 |
| :-- |
| 70 爬楼梯 |
| 整数拆分 |
| 不同的二叉搜索树 |
| 198 打家劫舍 |
| 213 打家劫舍 II |
| 337 打家劫舍 III |
上述中我们了解了什么是一维DP,接下来就是简单的 二维DP 。
简介
什么是 二维DP 呢?
我们知道我们使用一个一维数组就是 一维DP ,那么我们在 一维DP 里面再套一个 一维DP数组 则这个就是一个 二维DP 。简单来说 二维DP 就是 一维DP 中再包含一个 一维DP 。
走进二维DP
题目:
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
问总共有多少条不同的路径?
来源:力扣(LeetCode)
示例:
输入:m = 3, n = 7
输出:28
做题步骤:
我们能通过题目知道这是一个二维的空间,机器人能在这个二维空间经行下或右
的移动,当然 二维DP 也是一样首先需要确定一个 DP数组 ,然后确定推导公式,最后循环并得到结果。
思路:
当然啦,二维DP 当然要定义二维数组,推导公式是按照自己的需要来的。
本题的二维数组则就是网格的长和宽:
int[][] dp = new intp[m][n];
因为机器人只能向下和向右移动:
一种是从 (i-1, j) 这个位置走一步到达
一种是从(i, j - 1) 这个位置走一步到达
所以我们能得到其走到每个格子的路径(左边界和上边界的起始值都是1)的推导公式:相邻的左格子和上格子相加。
dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
循环则就需要嵌套循环,并且从(1,1)开始。
代码:
Python版本
一、Python所有方向的学习路线
Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照下面的知识点去找对应的学习资源,保证自己学得较为全面。
二、Python必备开发工具
工具都帮大家整理好了,安装就可直接上手!
三、最新Python学习笔记
当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。
四、Python视频合集
观看全面零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
五、实战案例
纸上得来终觉浅,要学会跟着视频一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
六、面试宝典
简历模板
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!