leetcode 121 股票买卖问题系列
描述:
给一些列数字,表示每条股票的价格,如果可以买卖一次(不能同一天买和卖),求最大利益(即差最大)。
其他三道问题是,如果能买卖无限次,买卖两次,买卖k次。
题一:
实质是求后面一个数减前一个数的最大差值。
维护一个最小值,和当前最大值。只需遍历一次,空间也是常数。
int maxProfit(vector<int>& prices) {
if (prices.size() < )
return ;
int min_ = prices[];
int ret = ;
for (int i = ; i < prices.size(); i++) {
ret = max(ret, prices[i] - min_);
min_ = min(min_, prices[i]);
}
return ret;
}
题二:
只要是后一个数比前一个大,都增。
int maxProfit(vector<int>& prices) {
if (prices.size() < )
return ;
int ret = ;
for (int i = ; i < prices.size() - ; i++) {
ret += max(prices[i + ] - prices[i], );
}
return ret;
}
题三:
可进行两次操作。
其中一个思路,可以关注分界点,可以枚举分界点,求左右两边的最优操作,在LeetCode会超时,显然,复杂度n^2。
思考下优化,我们可以计算每个点的最大值,左边不用重复计算,每次分界点往左移,都像题一那样计算最大值即可;
而右边,其实可以反向计算一遍,但是,右边改成求最小值。
最后加起来即可。
int maxProfit(vector<int>& prices) {
int size = prices.size();
if (size < )
return ;
int* left = new int[size]{};
int* right = new int[size]{};
int ret = ;
int lmin = prices[];
int lmax = ;
for (int i = ; i < size; i++) {
lmax = max(lmax, prices[i] - lmin);
left[i] = lmax;
lmin = min(lmin, prices[i]);
}
int rmin = ;
int rmax = prices[size - ];
for (int i = size - ; i >= ; i--) {
rmin = min(rmin, prices[i] - rmax);
right[i] = -rmin;
rmax = max(rmax, prices[i]);
}
for (int i = ; i < size - ; i++) {
ret = max(ret, left[i] + right[i + ]);
}
return max(ret, left[size - ]);
}
思路二:
int maxProfit(vector<int>& prices) {
int n = prices.size();
if(n==) return ;
int sell1 = , sell2 = , buy1 = INT_MIN, buy2 = INT_MIN;
for(int i =; i<n; i++)
{
buy1 = max(buy1, -prices[i]);
sell1 = max(sell1, prices[i]+buy1);
buy2 = max(buy2, sell1-prices[i]);
sell2 = max(sell2, prices[i]+buy2);
}
return sell2;
}
题四:
动态规划:
其中diff表示今天和昨天的差。
global[i][j] = max(local[i][j], global[i-1][j])
local[i][j] = max(global[i-1][j-1] + max(diff,0), local[i-1][j] + diff)
local[i][j]表示最后一次卖出在今天的最大利益,局部最优。
global[i][j]表示全局最优。
第一条式子:要么在今天卖出最优,要么前一天的全局最优。
第二条式子:前者为之前的全局最优加上最后一次交易在今天。
注意diff,我们要的是不大于j的交易次数;
如果i - 1天还持有,则i天卖出,共j - 1次操作;如果i-1天不持有,则i - 1天买入,i天卖出,共j次操作。
后者为i - 1天卖出加上今天diff,表示i - 1天还持有,加上今天的。
int maxProfit(int k, vector<int>& prices) {
if (prices.size() < ) return ;
int days = prices.size();
if (k >= days) return maxProfit2(prices);
auto local = vector<vector<int> >(days, vector<int>(k + ));
auto global = vector<vector<int> >(days, vector<int>(k + ));
for (int i = ; i < days ; i++) {
int diff = prices[i] - prices[i - ];
for (int j = ; j <= k; j++) {
local[i][j] = max(global[i - ][j - ], local[i - ][j] + diff);
global[i][j] = max(global[i - ][j], local[i][j]);
}
}
return global[days - ][k];
}
int maxProfit2(vector<int>& prices) {
int maxProfit = ;
for (int i = ; i < prices.size(); i++) {
if (prices[i] > prices[i - ]) {
maxProfit += prices[i] - prices[i - ];
}
}
return maxProfit;
}
类似题三的做法:
int maxProfit(int k, vector<int>& prices) {
int n = prices.size();
if(k>n/)
{
int buy = INT_MIN, sell = ;
for(int i=; i<n; i++)
{
buy = max(buy, sell-prices[i]);
sell = max(sell, buy+prices[i]);
}
return sell;
}
vector<int> sell(k+, );
vector<int> buy(k+, );
for(int i=; i<=k; i++) buy[i] = INT_MIN;
for(int i=; i<n; i++)
{
for(int j=; j<k+; j++)
{
buy[j] = max(buy[j], sell[j-]-prices[i]);
sell[j] = max(sell[j], buy[j]+prices[i]);
}
}
return sell[k];
}
leetcode 121 股票买卖问题系列的更多相关文章
- [LeetCode]121、122、309 买股票的最佳时机系列问题(DP)
121.买卖股票的最佳时机 题目 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润. 注意 ...
- leetcode 121
121. Best Time to Buy and Sell Stock Say you have an array for which the ith element is the price of ...
- 30. leetcode 121. Best Time to Buy and Sell Stock
121. Best Time to Buy and Sell Stock Say you have an array for which the ith element is the price of ...
- LeetCode 121. Best Time to Buy and Sell Stock (买卖股票的最好时机)
Say you have an array for which the ith element is the price of a given stock on day i. If you were ...
- LeetCode算法扫题系列19
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9104677.html LeetCode算法第19题(难度:中等) 题目:给定一个链表,删 ...
- LeetCode算法扫题系列83
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9104582.html LeetCode算法第83题(难度:简单) 题目:给定一个排序链表 ...
- [LeetCode] 121. Best Time to Buy and Sell Stock_Easy tag: Dynamic Programming
Say you have an array for which the ith element is the price of a given stock on day i. If you were ...
- leetcode 121. Best Time to Buy and Sell Stock 、122.Best Time to Buy and Sell Stock II 、309. Best Time to Buy and Sell Stock with Cooldown
121. Best Time to Buy and Sell Stock 题目的要求是只买卖一次,买的价格越低,卖的价格越高,肯定收益就越大 遍历整个数组,维护一个当前位置之前最低的买入价格,然后每次 ...
- [LeetCode] Matrix 值修改系列,例题 Surrounded Regions,Set Matrix Zeroes
引言 Matrix内部的值修改严格来讲放在一个系列里不大合适,因为对于不同的问题,所用的算法和技巧可能完全不同,权且这样归类,以后需要时再拆分吧. 例题 1 Given a 2D board cont ...
随机推荐
- js设计模式整理
单例模式 恶汉式单例 实例化时 懒汉式单例 调用时构造函数模式 1.实现一 function Car(model, year, miles) { this.model = model; this.ye ...
- iOS-----使用addressBook管理联系人之修改联系人
使用addressBook管理联系人之修改联系人 修改联系人 修改联系人先从底层地址簿中加载一条ABRecordRef记录,然后对这条ABRecordRef记录的属性值进行修改,修改完成后把这条修改后 ...
- Java第六次作业--异常处理和Java类集
Deadline: 2017-5-4 23:00 一.学习要点 认真看书并查阅相关资料,掌握以下内容: 理解Java的异常处理机制 掌握捕获异常和声明抛出异常的方法 掌握List接口的实现类Array ...
- Oozie_03运行官方案例【20161116】
3.1官方的案例 (1)Oozie根目录下找到 oozie-examples.tar.gz (2)解压tar -zxvf oozie-examples.tar.gz 生成example文件夹 [ha ...
- Loj 2005 相关分析
Loj 2005 相关分析 大力把式子拆开. \[ \begin{aligned} a &= \frac {\sum_{i=L}^{R} (x_i-\bar{x})(y_i-\bar{y})} ...
- 在Linux中批量修改字符串的命令
昨天一个朋友忽然问我,在Linux下如何批量修改字符串,当时瞬间懵逼了,完全想不起来....... 今天特意的重温了一下Linux下的一些常用命令,并将这个遗忘的批量修改字符串的命令记录下来(资料来自 ...
- 使用bit管理npm包
npm 包给共享,团队写作有好多问题需要解决,类似的解决方案有lerna yarn 使用monorepo,bit 官方有相关的比较 以下只说明如何进行简单的项目使用 网站 https://bitsrc ...
- linux shell获取用户输入
一.获取用户输入1.基本读取read命令接收标准输入的输入,或其它文件描述符的输入.得到输入后,read命令将数据输入放入一个标准变量中.[root@rac2 ~]# cat t8.sh #!/bin ...
- bzoj 4372 烁烁的游戏——动态点分治+树状数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4372 和 bzoj 3070 震波 是一个套路.注意区间修改的话,树状数组不能表示 dis ...
- 完全卸载vs2013、vs2015的方法
Visual Studio安装过程会安装好多组件,如果想要卸载的话会出现一些因难,在控制面板不容易卸载干净,在Linux下的命令都有--help参数来显示命令的用法,今天突发奇想,在控制台下输入vs2 ...