题目描述
在股市的交易日中,假设最多可进行两次买卖(即买和卖的次数均小于等于2),规则是必须一笔成交后进行另一笔(即买-卖-买-卖的顺序进行)。给出一天中的股票变化序列,请写一个程序计算一天可以获得的最大收益。请采用实践复杂度低的方法实现。
给定价格序列prices及它的长度n,请返回最大收益。保证长度小于等于500。
测试样例:
[10, 22, 5, 75, 65, 80], 6
返回:87
思路
划分(这不是二分法也不是分治算法)
1、计算所有位置的划分后的结果,比较得出最大。
2、在先把数组从中间分开,然后在两部分中分别找最大差值,然后保存最大差值进行相加。
3、完事之后,将中间的指针,也就是进行二分的指针向右或向左移。
4、又划分成了两部分,依次找最大差值,直到最后两个差值之和为最大值,返回最大值。
代码
public class Stock
{
private int findMax(int[] prices, int left, int right)
{
int min = Integer.MAX_VALUE;
int max = 0;
// i = left; i < right 说明是左闭区间右开区间
for (int i = left; i < right; i++)
{ // 找到一个更小值,那么就假定这一天买入(先预定买入,如果后面有更小的情况则更新)
if (prices[i] < min) min = prices[i];
// 如果股票涨了,有收益则预定卖出,同样如果出现收益更大的情况也会更新。
else if (prices[i] - min > max) max = prices[i] - min;
}
return max;
}
public int maxProfit(int[] prices, int n)
{
int resMax = 0;
// 划分点循环从头移动到尾
for (int i = 0; i < n - 1; i++)
{ // i等于0时表示一种特殊情况,即只够买一次的情况,这时等于求整个区间的最大差值(大值必须在小值后面的最大差值)
// 求出两边的最大收益
int maxLeft = findMax(prices, 0, i);
int maxRight = findMax(prices, i, n);
// 每次将两边的最大收益相加并于之前的比较,若更大就更新。
if (maxLeft + maxRight > resMax) resMax = maxLeft + maxRight;
}
return resMax;
}
}
注:本解题是参考牛客分享代码的同学的思路。其个人主页为:https://www.nowcoder.com/profile/7034296。当时昵称:cycleof