问题来源

题目来源链接见下方:
https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/description/

问题简述:

假如有一个 i 个元素的数组,数组的每个元素表示了第 i 天某只股票的价格,设计一种算法来找到利润最大的买卖方式。设计的算法必须遵守以下两条约束条件:

  • 在一天当中,只能进行“买”,“卖”或者“什么都不干”中的一种操作
  • 在“卖”掉股票之后,必须“什么都不干”一天

举个例子:

prices = [1, 2, 3, 0, 2]
maxProfit = 3
transactions = [buy, sell, cooldown, buy, sell]

解题思路

首先申明一下,这个思路并不是我想出来的,只是在LeetCode上看到有人这样解,觉得这个思路很不错,所以写下来作为分享和记录。
从题目中可以看出,不管哪一天,都只能是 buy 或者 sell 或者 cooldown(rest) 三种状态中的一种,而根据题目的约束条件,我们可以画出下图所示的状态图:

图1:状态描述图 由此图我们可以得到:

s0[i] = max(s0[i - 1], s2[i - 1])
s1[i] = max(s0[i - 1] - prices[i], s1[i - 1])
s2[i] = s1[i - 1] + prices[i]

其中s0,s1,s2分别表示三种状态下的最大利润值。
值得注意的是这里的s0,s1和s2不是单纯的buy,sell, rest,而应该是

s0 —— sell后rest或者rest后rest
s1 —— rest后的buy或者buy后的rest
s2 —— rest后的sell

同时,可以注意到的是,每次的状态 i 都只与前一次的状态 i - 1有关,也就是说我们可以把空间复杂度从O(n)降到O(1)。

解题代码

好了,话不多说,下面是时间复杂度为O(n),空间复杂度为O(1)的DP代码:

class Solution {
public:int maxProfit(vector<int>& prices) {if (prices.size() <= 1)return 0;int s0 = 0;int s1 = -prices[0];int s2 = INT_MIN;for (int i = 1; i < prices.size(); i++){int pre0 = s0;int pre1 = s1;int pre2 = s2;s0 = max(pre0, pre2);s1 = max(pre0 - prices[i], pre1);s2 = pre1 + prices[i];}//最大利润不可能出现在buy而未sell的时候,所以不考虑s1return max(s0, s2);}
};

结束语

利用动态规划解题的难点在于要搞清楚有哪些状态,每个状态是怎么来的,之后就是把状态用代码写出来了。
如有错误,还请指正~

LeetCode 309: 一个很清晰的DP解题思路相关推荐

  1. Leetcode 117. 填充每个节点的下一个右侧节点指针 II 解题思路及C++实现

    方法一:层序遍历 解题思路: 和第116题一模一样,其实,用队列queue更简单一些,不用将顺序倒来倒去.通过使用队列的长度信息queue.size(),可以只需要一个队列就能做到层序遍历. /* / ...

  2. LeetCode 496. 下一个更大元素 I 解题思路及C++实现

    解题思路: 因为这两个int型的vector中不包含重复元素,所以考虑使用c++中的unordered_map,对num2进行遍历,找到每一个元素的下一个更大元素,这样的话,时间复杂度就是O(n). ...

  3. Leetcode 138. 复制带随机指针的链表 解题思路及C++实现

    解题思路: 主要包括三步. 第一步是遍历一次链表,复制其每一个节点,并将所复制的节点接在其后. 第二步是遍历一次链表,解决拷贝节点的random指针的指向. 第三步是从这个大链表中,拆出原有链表和拷贝 ...

  4. LeetCode 272 Closest Binary Tree Traversal II 解题思路

    原题网址:https://leetcode.com/problems... Given a non-empty binary search tree and a target value, find  ...

  5. LeetCode 中等难度 92. 反转链表 II解题思路

    92. 反转链表 II 题目:中等难度 反转从位置 m 到 n 的链表.请使用一趟扫描完成反转. 说明: 1 ≤ m ≤ n ≤ 链表长度. 示例: 输入: 1->2->3->4-& ...

  6. Leetcode 209. 长度最小的子数组 解题思路及C++实现

    解题思路: 定义两个指针 left 和 right,构成一个滑动窗口,当窗口内的数值和小于 s 时,右指针向右滑动,当窗口内的数值和大于等于 s 时,就要更新一次 子数组的最小长度了.同时 左指针向右 ...

  7. Leetcode 96. 不同的二叉搜索树 解题思路及C++实现

    解题思路: 因为二叉搜索树的左右子树均为二叉搜索树.输入整数n,求其所有二叉搜索树的总数,就是求根节点分别为1,2, ..., n的二叉搜索树的总和. 假设 i 的二叉搜索树的总数为 f(i),当根节 ...

  8. Leetcode 107. 二叉树的层次遍历 II 解题思路及C++实现

    解题思路: 使用队列实现二叉树的层序遍历,因为题目中要求每一层的val存储在一个vector中,所以在内循环中,还需要一个队列,用以存储更新每一层的节点. 在最后,需要将得到的res数组逆序. /** ...

  9. Leetcode 349. 两个数组的交集 解题思路及C++实现

    解题思路: 先对数组进行排序,然后从小到大去找相同的元素. 程序大循环是遍历两个数组. 循环体内,当找到相等的数之后,要注意跳过重复的数字. class Solution { public:vecto ...

最新文章

  1. 0709 C语言常见误区----------函数指针问题
  2. python采集_Python采集实例2
  3. mac os android连接wifi密码,Mac使用小技巧:找回WiFi密码
  4. 用标准C语言初始化线性表,跪求:线性表初始化函数的详细解释(c语言)
  5. 无效内卷正在毁掉年轻一代程序员
  6. Python安装常见问题:ModuleNotFoundError: No module named ‘_ctypes‘ 解决办法
  7. WebSocket 对象简介
  8. mongodb 正则
  9. MFC windows程序设计(第三版)课后习题第一章
  10. 传奇修改map地图教程_传奇地图MAP编辑器
  11. 【算法】-8大排序算法总结-Python
  12. 推荐3个干净、资源多的看剧网站给大家
  13. python图例重复显示_python matplotlib图例重复
  14. 天龙 - Terrain
  15. ブリアー / 三星枪
  16. 通过官网怎么查找联盟申请链接
  17. 【常用芯片】ULN2003工作原理及中文资料(实例:STM32驱动28BYJ48步进电机)
  18. 平面设计新手怎么构思设计?有什么技巧!
  19. 冈萨雷斯matlab工具箱,MATLAB版冈萨雷斯+中文高清版.pdf
  20. ①简单介绍与电路简化

热门文章

  1. 创建office一直转圈_Windows写字板出现广告条幅:推荐用户使用在线版Office
  2. 计算机如何添加管理员权限,电脑使用代码如何添加管理员权限
  3. 大数据之Kafka入门简介
  4. 集合添加元素python_Python基础:列表、字典、元组、集合、添加和删除元素,增删...
  5. Python3.10 结构化模式匹配 PEP 634
  6. java metric_java版的Metric工具介绍
  7. spring restTemplate使用方法
  8. 汇编_指令_FLAGS
  9. 【转】java单例模式的实现
  10. SQL SERVER PIVOT 行转列、列传行