剑指offer11——动态规划(简单)
剑指 Offer 10- I. 斐波那契数列
难度 简单
写一个函数,输入 n
,求斐波那契(Fibonacci)数列的第 n
项(即 F(N)
)。斐波那契数列的定义如下:
1 | F(0) = 0, F(1) = 1 |
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
示例 1:
1 | 输入:n = 2 |
示例 2:
1 | 输入:n = 5 |
提示:
0 <= n <= 100
思路与题解
-
**状态定义:**F[i]为第i个斐波那契数列的数字
-
转移方程:$F[i] = F[i-1]+F[i-2]$
-
初始状态:$F[0]=0;F[1]=1$
-
**计算顺序:**从0开始向目标迭代
代码
1 | class Solution { |
剑指 Offer 10- II. 青蛙跳台阶问题
难度 简单
一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n
级的台阶总共有多少种跳法。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
示例 1:
1 | 输入:n = 2 |
示例 2:
1 | 输入:n = 7 |
示例 3:
1 | 输入:n = 0 |
提示:
0 <= n <= 100
注意:本题与主站 70 题相同:https://leetcode-cn.com/problems/climbing-stairs/
思路与题解
由于最后一级台阶只能从倒数第二级和倒数第三级跳上来,所以
跳上第n个台阶的方法数量 = 跳上第n-1个台阶的方法数量 + 跳上第n-2个台阶的方法数量
所以本题和斐波那契数列的题是一致的,只不过初始条件由$F(0) = 0,F (1) = 1,F(2) = 1$变成了$F(0) = 1,F (1) = 1,F(2) = 2$
代码
1 | /* |
剑指 Offer 63. 股票的最大利润
难度 中等
假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少?
示例 1:
1 | 输入: [7,1,5,3,6,4] |
示例 2:
1 | 输入: [7,6,4,3,1] |
限制:
1 | 0 <= 数组长度 <= 10^5 |
思路与题解
假设输入为[7,1,5,3,6,4]
分解问题并缩小为六个子问题:
1 | [7,1,5,3,6,4] -> max = 5 |
则
$$
F[n] = max( F[n-1], max(prices[n] - prices[i]))
$$
即 F[n] 为过去的最高利润 与 在第n日卖出时利润更高者
但是这里我用了两个循环来解,把时间复杂度整高了。。。导致了超时。。。
代码
1 | /* |
思路2
大佬的思路:
大佬的转移方程写的比我的清楚:
$$
前i日最大利润=\max(前(i−1)日最大利润,第i日价格−前i日最低价格)\
dp[i]=\max(dp[i−1],prices[i]−\min(prices[0:i]))
$$
时间复杂度降低: 前 $i$ 日的最低价格 $min(prices[0:i]) $时间复杂度为 $O(i)$ 。而在遍历 $prices$时,可以借助一个变量(记为成本 $cost$ )每日更新最低价格。优化后的转移方程为:
$$
dp[i]=\max(dp[i−1],prices[i]−\min(cost,prices[i]))
$$
空间复杂度降低: 由于$ dp[i]$ 只与 $dp[i - 1] , prices[i] , cost$ 相关,因此可使用一个变量(记为利润 $profit$ )代替 $dp $列表。优化后的转移方程为:
$$
profit = \max(profit, prices[i] - \min(cost, prices[i])
$$
1 | /* |