【LeetCode】123、买卖股票的最佳时机 III
Best Time to Buy and Sell Stock III
题目等级:Hard
题目描述:
Say you have an array for which the ith element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete at most two transactions.
Note: You may not engage in multiple transactions at the same time (i.e., you must sell the stock before you buy again).
Example 1:
Input: [3,3,5,0,0,3,1,4]
Output: 6
Explanation: Buy on day 4 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3.
Then buy on day 7 (price = 1) and sell on day 8 (price = 4), profit = 4-1 = 3.
Example 2:
Input: [1,2,3,4,5]
Output: 4
Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.
Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are
engaging multiple transactions at the same time. You must sell before buying again.
Example 3:
Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.
题意:给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。设计一个算法来计算所能获取的最大利润。最多允许完成两次交易,必须在再次购买前出售掉之前的股票。
解题思路(动态规划+二分法):
前面两道题分别是允许一次交易和允许无数次交易,这里的改变是允许两次交易,相对难度就比较大。
首先回顾一下允许一次交易的情形,买卖股票的问题我们可以看到是一个明显的分阶段决策的问题,每一阶段的决策会影响到整体的决策,从而影响最优化结果。所以在一次交易问题中,我们使用动态规划,采用以下递推公式进行解决:dp[i]=max(price[i]-min,maxProfit)
。
这里是两次交易,解法是:将两次交易转化成两个一次交易,第i天之前一次,第i天之后一次。
我们可以看到,两次交易一定是先完成了一次,接下来再完成第二次,所以可以使用二分的思想,以第i天为分界,第i天之前完成一次交易,第i天之后完成一次交易,分别得到每一次交易的最大值,最后遍历一次找到最合适的i,则对应的两次收益之和就是我们求的结果。
我们用dp1[i]表示从第一天到第i天完成一次交易的最大收益,用dp2[i]表示从第i天到最后一天完成一次交易的最大收益。则只需要分别计算出这两个数组dp1和dp2即可。
对于dp1,很简单,从前往后遍历,这就是我们在一次遍历时的递推公式:dp1[i]=max(dp[i-1],prices[i]-min)
对于dp2,稍作变形,从后往前遍历,维护一个最大值,递推公式:dp2[i]=max(dp[i+1,max-prices[i]])
最后,我们要求的结果就是:res=max(dp1[i]+dp2[i])
,也就是找到最合适的i值。
class Solution {
public int maxProfit(int[] prices) {
/*分成两次,第i天之前一次,第i天之后一次,转化成两个一次交易的问题
从前往后:dp1[i]=max(dp[i-1],prices[i]-min),从第一天到第i天完成一次交易的最大收益
从后往前:dp2[i]=max(dp[i+1,max-prices[i]]),从第i天到最后一天完成一次交易的最大收益
*/
if(prices==null || prices.length==0)
return 0;
int len=prices.length;
int[] dp1=new int[len];
int[] dp2=new int[len];
//从前往后
int min=prices[0];
dp1[0]=0;
for(int i=1;i<len;i++){
dp1[i]=Math.max(dp1[i-1],prices[i]-min);
min=Math.min(prices[i],min);
}
//从后往前
int max=prices[len-1];
dp2[len-1]=0;
for(int i=len-2;i>=0;i--){
dp2[i]=Math.max(max-prices[i],dp2[i+1]);
max=Math.max(prices[i],max);
}
//合并得到结果
int res=0;
for(int i=0;i<len;i++){
if(dp1[i]+dp2[i]>res)
res=dp1[i]+dp2[i];
}
return res;
}
}
时间复杂度:O(3n),空间复杂度:O(2n)
总结
本题难度比较大,实际上这就是一次交易的变形考法,主要是要熟悉动态规划的解法,正确写出递推公式。
【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 笔交易. 注意: 你不能同时参与多 ...
随机推荐
- Gym - 102040F Path Intersection (树链剖分+线段树)
题意:给出棵树上的k条路径,求这些路径的公共点数量. 将每条路径上的点都打上标记,被标记过k次的点就是公共点了.由于公共点形成的区间是连续的,因此直接在线段树上暴搜即可在$O(logn)$求出一条链上 ...
- js array map() 函数的简单使用
语法: array.map(function(currentValue,index,arr), thisValue) currentValue:必须.当前元素的值 index:可选.当前元素的索引值 ...
- Oracle数据库查询优化方案
1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引.2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引 ...
- qt5--列表控件QListWidget
需要 #include <QListWidget> #include <QListWidgetItem> 列表控件可以让我们以列表形式呈现内容,是界面 ...
- SpringBoot项目中,WebSocket的使用(观察者设计模式)
1.什么是WebSocket(选择至菜鸟教程(点击跳转),观察者模式) WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议. WebSocket 使得客户端和 ...
- Angular 主从组件
此刻,HeroesComponent 同时显示了英雄列表和所选英雄的详情. 把所有特性都放在同一个组件中,将会使应用“长大”后变得不可维护. 你要把大型组件拆分成小一点的子组件,每个子组件都要集中精力 ...
- C++常用string函数
来自https://www.cnblogs.com/jm-Xu/p/9318705.html string(s小写)是C++标准库中的类,纯C中没有,使用时需要包含头文件#include<str ...
- win10 + cuda10.0 + pytorch1.2 + CenterNet 环境搭建
心血来潮,想跑个 CenterNet 检测瞅瞅...麻蛋,有非官方层 一.下载好 CenterNet 源码 https://github.com/xingyizhou/CenterNet 二.注意你需 ...
- HDU2082 找单词
问题分析 不难想到用母函数做. 令自变量\(x\)的次数就是单词价值,那么答案就是\(x\)的\(1\)次到\(50\)次的系数之和.由于我们只需要处理前\(51\)项,所以暴力多项式相乘即可. 举个 ...
- [LOJ3109][TJOI2019]甲苯先生的线段树:DP
分析 首先,请允许我 orz HN队长zsy.链接 我们发现树上的链有两种类,一类是直上直下的,一类不是直上直下的(废话).并且,如果我们确定了左侧和右侧的链的长度和整条链上所有节点的编号之和,那么这 ...