LeetCode(123):买卖股票的最佳时机 III
Hard!
题目描述:
给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。
注意: 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例 1:
输入: [3,3,5,0,0,3,1,4]
输出: 6
解释: 在第 4 天(股票价格 = 0)的时候买入,在第 6 天(股票价格 = 3)的时候卖出,这笔交易所能获得利润 = 3-0 = 3 。
随后,在第 7 天(股票价格 = 1)的时候买入,在第 8 天 (股票价格 = 4)的时候卖出,这笔交易所能获得利润 = 4-1 = 3 。
示例 2:
输入: [1,2,3,4,5]
输出: 4
解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。
因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。
示例 3:
输入: [7,6,4,3,1]
输出: 0
解释: 在这个情况下, 没有交易完成, 所以最大利润为 0。
解题思路:
这道是买股票的最佳时间系列问题中最难最复杂的一道,前面两道Best Time to Buy and Sell Stock 买卖股票的最佳时间和Best Time to Buy and Sell Stock II 买股票的最佳时间之二的思路都非常的简洁明了,算法也很简单。
而这道是要求最多交易两次,找到最大利润,还是需要用动态规划Dynamic Programming来解,而这里我们需要两个递推公式来分别更新两个变量local和global,参见https://blog.csdn.net/linhuanmars/article/details/23236995,
我们其实可以求至少k次交易的最大利润,找到通解后可以设定 k = 2,即为本题的解答。我们定义local[i][j]为在到达第i天时最多可进行j次交易并且最后一次交易在最后一天卖出的最大利润,此为局部最优。然后我们定义global[i][j]为在到达第i天时最多可进行j次交易的最大利润,此为全局最优。它们的递推式为:
local[i][j] = max(global[i - 1][j - 1] + max(diff, 0), local[i - 1][j] + diff)
global[i][j] = max(local[i][j], global[i - 1][j])
其中局部最优值是比较前一天并少交易一次的全局最优加上大于0的差值,和前一天的局部最优加上差值中取较大值,而全局最优比较局部最优和前一天的全局最优。
C++解法一:
class Solution {
public:
int maxProfit(vector<int> &prices) {
if (prices.empty()) return ;
int n = prices.size(), g[n][] = {}, l[n][] = {};
for (int i = ; i < prices.size(); ++i) {
int diff = prices[i] - prices[i - ];
for (int j = ; j <= ; ++j) {
l[i][j] = max(g[i - ][j - ] + max(diff, ), l[i - ][j] + diff);
g[i][j] = max(l[i][j], g[i - ][j]);
}
}
return g[n - ][];
}
};
下面这种解法用一维数组来代替二维数组,可以极大地节省空间,由于覆盖的顺序关系,我们需要j从2到1,这样可以取到正确的g[j-1]值,而非已经被覆盖过的值。
C++解法二:
class Solution {
public:
int maxProfit(vector<int> &prices) {
if (prices.empty()) return ;
int g[] = {};
int l[] = {};
for (int i = ; i < prices.size() - ; ++i) {
int diff = prices[i + ] - prices[i];
for (int j = ; j >= ; --j) {
l[j] = max(g[j - ] + max(diff, ), l[j] + diff);
g[j] = max(l[j], g[j]);
}
}
return g[];
}
};
我们如果假设prices数组为1, 3, 2, 9, 那么我们来看每次更新时local 和 global 的值:
第一天两次交易: 第一天一次交易:
local: 0 0 0 local: 0 0 0
global: 0 0 0 global: 0 0 0
第二天两次交易: 第二天一次交易:
local: 0 0 2 local: 0 2 2
global: 0 0 2 global: 0 2 2
第三天两次交易: 第三天一次交易:
local: 0 2 2 local: 0 1 2
global: 0 2 2 global: 0 2 2
第四天两次交易: 第四天一次交易:
local: 0 1 9 local: 0 8 9
global: 0 2 9 global: 0 8 9
在网友@loveahneehttps://home.cnblogs.com/u/1221269/的提醒下,发现了其实上述的递推公式关于local[i][j]的可以稍稍化简一下,我们之前定义的local[i][j]为在到达第i天时最多可进行j次交易并且最后一次交易在最后一天卖出的最大利润,然后网友@fgvltyhttps://home.cnblogs.com/u/985421/解释了一下第 i 天卖第 j 支股票的话,一定是下面的一种:
1. 今天刚买的
那么 Local(i, j) = Global(i-1, j-1)
相当于啥都没干
2. 昨天买的
那么 Local(i, j) = Global(i-1, j-1) + diff
等于Global(i-1, j-1) 中的交易,加上今天干的那一票
3. 更早之前买的
那么 Local(i, j) = Local(i-1, j) + diff
昨天别卖了,留到今天卖
但其实第一种情况是不需要考虑的,因为当天买当天卖不会增加利润,完全是重复操作,这种情况可以归纳在global[i-1][j-1]中,所以我们就不需要max(0, diff)了,那么由于两项都加上了diff,所以我们可以把diff抽到max的外面,所以更新后的递推公式为:
local[i][j] = max(global[i - 1][j - 1], local[i - 1][j]) + diff
global[i][j] = max(local[i][j], global[i - 1][j])
LeetCode(123):买卖股票的最佳时机 III的更多相关文章
- Java实现 LeetCode 123 买卖股票的最佳时机 III(三)
123. 买卖股票的最佳时机 III 给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你最多可以完成 两笔 交易. 注意: 你不能同时参与 ...
- Leetcode 123.买卖股票的最佳时机III
买卖股票的最佳时机III 给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你最多可以完成 两笔 交易. 注意: 你不能同时参与多笔交易(你 ...
- leetcode 123. 买卖股票的最佳时机 III JAVA
题目: 给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你最多可以完成 两笔 交易. 注意: 你不能同时参与多笔交易(你必须在再次购买前出 ...
- leetcode 123. 买卖股票的最佳时机 III
使用动态规划的解法,空间复杂度O(2*2)如果交易k次则为O(2*k),时间复杂度O(2n),交易k次为O(n*k), 因此本题实际上可以退化为买卖一次的情况:去掉buy2和sell2,即leetco ...
- Leetcode之动态规划(DP)专题-123. 买卖股票的最佳时机 III(Best Time to Buy and Sell Stock III)
Leetcode之动态规划(DP)专题-123. 买卖股票的最佳时机 III(Best Time to Buy and Sell Stock III) 股票问题: 121. 买卖股票的最佳时机 122 ...
- 【力扣】123. 买卖股票的最佳时机 III
给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你最多可以完成 两笔 交易. 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的 ...
- [Leetcode]123.买卖股票的最佳时机3
[原题链接][https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iii/] 分析:动态规划+二分法.以第i天为分界线,计 ...
- 每日一题-——LeetCode(121)买卖股票的最佳时机
题目描述: 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格.如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润.注意你不能在买入股票前卖出股票 ...
- lintcode:买卖股票的最佳时机 III
买卖股票的最佳时机 III 假设你有一个数组,它的第i个元素是一支给定的股票在第i天的价格.设计一个算法来找到最大的利润.你最多可以完成两笔交易. 样例 给出一个样例数组 [4,4,6,1,1,4,2 ...
- Java实现 LeetCode 188 买卖股票的最佳时机 IV
188. 买卖股票的最佳时机 IV 给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你最多可以完成 k 笔交易. 注意: 你不能同时参与多 ...
随机推荐
- Python的参数类型
参数类型: 1.必填参数,位置参数(positional arguments,官方定义,就是其他语言所说的参数) 2.默认值参数,非必传 3.可变参数,非必传,不限制参数个数,比如说给多个人发邮件,发 ...
- java 基础 字符类型
1.char类型的字面量可以是一个英文字母.字符或一个汉字,并且由单引号包括. 2.Java底层使用一个16位的整数来处理字符类型,该数值是一个字符的unicode编码值. unicode: 1.un ...
- [转] 使用gc && objgraph 优化python内存
转自https://www.cnblogs.com/xybaby/p/7491656.html 使用gc.objgraph干掉python内存泄露与循环引用! 目录 一分钟版本 python内存管 ...
- 为什么python运行的慢
最近在leetcode刷题,明显的注意到同样的算法,python运行的要慢的多,查资料得到python运行的慢主要原因如下: 一.动态类型导致运行速度慢,在北邮人论坛里面的这篇帖子中有较为详细的解释, ...
- Android AlertDialog 绝对位置计算
public class Main2Activity extends AppCompatActivity { @Override protected void onCreate(Bundle save ...
- 手写代码注意点--java.util.Stack相关
1-Stack的基本函数为: 注意: 取栈顶的函数为peek(),不是top()... 测试stack是否为空的函数为empty(),不是isEmpty()...
- 【转】Linux下查看系统配置
[转]Linux下查看系统配置 CPU 1. lscpu:显示cpu架构信息 [xxx@localhost ~]$ lscpu Architecture: x86_64 CPU op-mode(s): ...
- 用vue+element-ui开发后台笔记
1.前端通过 formData: new FormData(), 构造对象传数值给后台! 当传给后台的参数中有图片的时候,需要把需要传输的数据通过构造对象new FormData()的形式存数据,并且 ...
- window安装mysql(详细步骤)
前两天电脑炸了,就重新装了系统重新安装了一遍mysql. 首先 你需要有一个安装包哈哈哈,mysql的安装包. 最好不要安装在c盘呦~ 来进入正题吧... ********************** ...
- day2 --> pyc 文件
执行python 代码时,如果导入了其他的.py文件,那么,执行过程中会自动生成一个与其同名的.pyc文件,该文件就是python解释器便宜之后产生的字节码. PS:代码经过便宜可以产生字节码;字节码 ...