大家好,今天和大家分享一道动态规划的题目:买卖股票的最佳时机
让我们一起来看看这道题目吧!
描述
假设你有一个数组,其中第 i\ i i 个元素是股票在第 i\ i i 天的价格。
你有一次买入和卖出的机会。(只有买入了股票以后才能卖出)。请你设计一个算法来计算可以获得的最大收益。
思路
这个股票只能买一次,卖一次。卖要在买之前。
给出一个数组,一个简单的思路就是:把数组看成一个折线图,顶点的位置是我们要卖的时机。那么什么时候买呢?就是从开头到顶点位置里面的最小值。
实际上这是一个全局比较的策略,我把所有可能的最大值都列出来,在里面选一个最大的
这里面顶点(最低点+最高点)有1,2,3,4,5,6.
首先在[0,arr.length-1]上找局部最大值,这里第一次寻找的时候局部最大就是全局最大,那很明显就是4了。
有人要问:不是找顶点吗?第一个出现的顶点明明是2,为什么先选4了呢?
我们先继续往下看,选完顶点之后,再选从[0,顶点4代表坐标]中选一个最小的值,图里面就是1了。
那么,股票买入的时机是1位置,卖出的时机是4位置。那么这个2位置的顶点我们把它忽略。为什么?我在1买入,可以在2卖出,因为在逻辑上它会创造可能的最大收益。但是后面有一个比它还大的4位置,为什么我不在4位置卖出,获取更大的收益呢?所以这就是选取局部最大的原因。记为sum.
之后从4位置+1的地方往后看,再选取一个局部最大,再选一个局部最小,再得到一个值,和sum比较,sum取大的值。
public int maxProfit (int[] prices) {
// write code here
if(prices == null || prices.length < 1)return 0;
if(prices.length == 1)return 0;
if(prices.length == 2) return Math.max(prices[1] - prices[0], 0);
return pro(prices,0);
}
// 从index位置往后看,此时状态是没买入,没卖出
// 在index位置往后的区间进行股票操作的最大值
public static int pro(int[] a,int index){
// baseCase
if(index >= a.length) return 0;
if(index == a.length-1) return 0;
// 当前位置下标cur
int cur = index;
// 记录max位置的下标
int max = cur;
//选max
while (cur < a.length){
if(a[cur] > a[max]) {
max = cur;
}
cur++;
}
//从初始位置处选最小值
cur = index;
int min = cur;
while (cur <= max){
if(a[cur] < a[min]) {
min = cur;
}
cur++;
}
// 比较,继续递归往后寻找
return Math.max((a[max] - a[min]),pro(a,max+1));
}
分割线分割线分割线分割线分割线分割线分割线分割线分割线分割线分割线分割线分割线分割线分割线分割线分割线分割线分割线分割线分割
那么回到我们的主题:最佳买卖股票时机含冷冻期
回不去了:《 我们下期再见!