
动态规划的学习—从暴力递归到动态规划
如果 如果已经买入( 如果没有买入(
发布日期:2021-05-07 16:07:34
浏览次数:17
分类:精选文章
本文共 2118 字,大约阅读时间需要 7 分钟。
lc343 | 买股票问题
在这里,我们将从暴力递归开始,然后逐步改写为动态规划。
暴力递归思路
我们可以采用递归的方法来解决这个问题。假设我们有一个数组 prices
,记录股票的价格。每一天,我们可以选择买入、卖出或者不买入股票。递归函数 dfs
可以接受当前的索引 index
和一个布尔 flag
,表示是否已经买入股票。
递归函数的逻辑如下:
index
超过了数组的长度,说明交易结束,返回0利润。flag
为 true
),那么只能卖出,计算利润,然后递归。flag
为 false
),则有三种选择: - 继续观望,不买入,递归
index + 1
,flag
不变。 - 买入,记录利润,然后递归
index + 1
,flag
变为true
。 - 卖出,计算利润,然后递归
index + 1
,flag
变为false
。
为了优化递归,我们需要使用记忆化来缓存已经计算过的状态。
动态规划思路
既然我们已经写出了递归函数,我们可以将递归的状态转换为动态规划的状态转移方程。我们可以使用一个二维数组 dp
,其中 dp[i][j]
表示到第 i
个交易日,处于状态 j
(j = 0
表示没买,j = 1
表示买)的最大利润。
- 初始化:
dp[n][0] = 0
,dp[n][1] = -prices[n-1]
(这里n
是数组的长度)。 - 从
n-1
往回推,计算每一天的最大利润:- 对于每一天
i
:- 如果当前状态是没买(
j=0
),那么最大利润可以是买入后卖出的利润加上后续的最大利润,或者不买入,继续后续的最大利润。 - 如果当前状态是买入(
j=1
),那么只能卖出,得到利润,加上后续的最大利润。
- 如果当前状态是没买(
- 对于每一天
代码
递归代码:
#includeusing namespace std;class Solution { int dfs(const vector & prices, int index, bool flag) { if (index >= prices.size()) return 0; if (flag) { return 0 - prices[index] + dfs(prices, index + 1, false); } else { int buy = 0 - prices[index] + dfs(prices, index + 1, true); int not_buy = dfs(prices, index + 1, false); return max(buy, not_buy); } }public: int maxProfit(vector prices) { return dfs(prices, 0, true); }};
动态规划代码:
class Solution {public: int maxProfit(vector prices) { int n = prices.size(); vector> dp(n + 1, vector (2, 0)); dp[n][0] = 0; dp[n][1] = -prices[n - 1]; for (int i = n - 1; i >= 0; --i) { for (int j = 0; j < 2; ++j) { dp[i][j] = dp[i + 1][j]; if (j == 0) { dp[i][j] = max(dp[i][j], dp[i + 1][1] + prices[i]); } else { dp[i][j] = max(dp[i][j], dp[i + 1][0] - prices[i]); } } } return dp[0][1]; }};
代码说明
递归代码:
dfs
函数接受当前索引和是否已经买入的状态。- 如果已经买入(
flag
为true
),则卖出,计算利润,并递归下一天。 - 如果没有买入(
flag
为false
),则有三种选择:买入、卖出或不买入,返回最大利润。
动态规划代码:
- 使用二维数组
dp
,记录每一天的最大利润。 - 从最后一天开始,向前填充
dp
表。 - 状态转移方程根据递归的逻辑进行填充,最终返回
dp[0][1]
,即最大的利润。
发表评论
最新留言
关注你微信了!
[***.104.42.241]2025年04月10日 13时54分04秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
7.3 制定预算
2019-03-04
习惯养成记打卡-第7章 项目成本管理
2019-03-04
习惯养成记打卡-第9章 项目资源管理
2019-03-04
LeetCode - 98. 验证二叉搜索树(迭代、递归)2
2019-03-04
【△重点△】LeetCode - 4. 寻找两个正序数组的中位数——二分查找
2019-03-04
LeetCode - 5. 最长回文子串——字符串、动态规划
2019-03-04
【BFS】——LeetCode - 752. 打开转盘锁
2019-03-04
【快慢指针】——LeetCode - 287. 寻找重复数
2019-03-04
【数据结构系列】链表合并问题——链表的奇偶重排
2019-03-04
【Redis】Redis客户端实现的基本原理
2019-03-04
全局锁和表锁 :给表加个字段怎么有这么多阻碍?
2019-03-04
事务到底是隔离的还是不隔离的?
2019-03-04
SpringMVC的Model对象的使用
2019-03-04
文本读取和csv文件生成工具类的编写
2019-03-04
@Import注解---导入资源
2019-03-04
Leetcode 面试题 08.04. 幂集(DAY 103) ---- 回溯算法学习期
2019-03-04
重读&笔记系列-《Linux多线程服务端编程》第一章
2019-03-04
解决ubuntu在虚拟机(VMware)环境下不能联网的问题
2019-03-04
LeetCode - 字符串相乘
2019-03-04
C# 适配器模式
2019-03-04