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 笔交易. 注意: 你不能同时参与多 ...
随机推荐
- mysql 无法链接, 输入密码失败
今天,在外面上网,使用的是公网(好像不安全,我也不懂),然后连接数据库,出现下面错误,我明明输入正确的密码还是失败了. 然后我在网上查方式, 应该是没有设置开机启动,输入了: mysqld --con ...
- mongodb 系列 ~ mongo的两种引擎介绍对比
一 简介 两种引擎方式的对比二 对比与说明 1 版本支持 MMAP引擎 3.2版本之前,默认引擎 WT 引擎 3.2版本之后,默认引擎 2 并发性能(核心) M ...
- Python问题:UnboundLocalError: local variable 'xxx' referenced before assignment
参考链接: http://blog.csdn.net/onlyanyz/article/details/45009697 https://www.cnblogs.com/fendou-999/p/38 ...
- Javascript - ExtJs - GridPanel组件
GridPanel组件(Ext.grid.GridPanel)logogram:Ext.grid.Panel | xtype:gridpanel 此类派生自Ext.Panel,创建表格需要两个必须的对 ...
- (ScrollViewer或者有滚动条的控件)嵌套一个(ScrollViewer或者有滚动条的控件)禁用里面的滚动条
转自:http://blog.csdn.net/haylhf/article/details/8351203 后有改动 在C# 中,两个ScrollViewer嵌套在一起或者ScrollViewer里 ...
- SpringMVC中前后端Date交互
建议使用时间戳来避免日期格式带来的前后端问题,使用时间戳可以避免前后端.平台等问题. new Date().getTime()
- json文件解析
场景 读取json文件,读取子域名扫描结果 实现 >>> import json >>> with open("C:\\Users\\Windows32\ ...
- Linux虚拟机安装及环境搭建
1.下载centos,地址:https://www.centos.org/download/ 下载时选择DVD ISO 2.使用VMware Workstation进行安装. 3.虚拟机网络配置 ...
- Memcached技术
Memcached技术 介绍: memcached是一种缓存技术, 他可以把你的数据放入内存,从而通过内存访问提速,因为内存最快的, memcached技术的主要目的提速, 在memachec 中维护 ...
- C++游戏开发需要阅读的书籍
如果要自学游戏程序开发的话,可以看看下面的,呵呵. 游戏开发资料(PDF书都是中文版的,非英文,很多是本人自己扫描制作,从未网上发布过,所以独家啦): 1.Gamebryo 2.2游戏引擎(盛大.腾 ...