参考文献:http://blog.csdn.net/li563868273/article/details/51073838
解析:动态规划思路,有0次,1次,2次机会操作股票,那么可以把数组以i为中间值分为前半段和后半段,0<=i<=n-1,dpl[i]表示从0到i-1天内的最大收益,dpr[i]表示从第i-1天到第n-1天内的最大收益,两者相加可求出总的最大收益
import java.sql.ResultSet;
public class Main {
public static void main(String[] args) {
int[] array = new int[] { 3, 8, 5, 1, 7, 8 };
calculateMax3(array);
}
public static int calculateMax(int[] p) {
int[] dpl=new int[p.length];
//dpl[i]为从0开始到i的所有天中能获得的最大的收益,可能是其中的一段时间
int length=p.length;
dpl[0]=0;
int min=0;
//min为从第min天开始买入到第i天获得的收益
int resl=0;
for(int i=1;i<length;i++){
if(p[i]>p[i-1]){
resl=Math.max(p[i]-p[min], resl);//比较值为历史新低到当前天的最大收益和前i天历史最大值
dpl[i]=resl;
//若第二天上涨,有可能该天到买入收益最大,也有可能是股票回升
//若股票回升,则还是为前i天最大值,即前i天最大收益仍为第min天到第某天
}else {
//若第二天下跌,则看是否跌出谷底,
//若没有跌出谷底,则仍为前i-1天最大收益
//若跌出谷底则重新计算最小值,从该天算后面的收益
dpl[i]=dpl[i-1];
if(p[i]<p[min]){
min=i;
}
}
}
int[] dpr=new int[length];
dpr[length-1]=0;
int resr=0;
int max=length-1;
for(int i=length-2;i>=0;i--){
if(p[i]<p[i+1]){
resr=Math.max(p[max]-p[i], resr);
dpr[i]=resr;
}else {
dpr[i]=dpr[i+1];
if(p[i]>p[max]){
max=i;
}
}
}
int res =0;
for(int i=0;i<length;i++){
res=Math.max((dpl[i]+dpr[i]), res);
}
System.out.println(res);
return res;
}
/**
* 计算你能获得的最大收益
*
* @param prices
* Prices[i]即第i天的股价
* @return 整型
*/
public static int calculateMax2(int[] prices) {
int firstBuy = Integer.MIN_VALUE, firstSell = 0;
int secondBuy = Integer.MIN_VALUE, secondSell = 0;
for (int curPrice : prices) {
firstBuy = Math.max(firstBuy, -curPrice);
firstSell = Math.max(firstSell, firstBuy + curPrice);
secondBuy = Math.max(secondBuy, firstSell - curPrice);
secondSell = Math.max(secondSell, secondBuy + curPrice);
System.out.println("firstBuy: " + firstBuy + ", firstSell: "
+ firstSell + ", secondBuy: " + secondBuy
+ ", secondSell: " + secondSell);
}
return secondSell;
}
// 来自http://blog.csdn.net/li563868273/article/details/51073838
public static int calculateMax3(int[] prices) {
// 记录[0..i]之间的最大收益
int[] dpl = new int[prices.length];
// 记录[i...length-1]的最大收益
int[] dpr = new int[prices.length];
dpl[0] = 0;// 第一个肯定赋值为0
int minI = 0;
// 扫描一次左边
System.out.print("dpl[0]=0, ");
for (int i = 1; i < dpl.length; i++) {
// 如果大于等于
if (prices[i] > prices[i - 1]) {
dpl[i] = Math.max(prices[i] - prices[minI], dpl[i - 1]);
} else {
dpl[i] = dpl[i - 1];
if (prices[i] < prices[minI])
minI = i;
}
System.out.print("dpl[" + i + "]=" + dpl[i] + ", ");
}
System.out.println();
// 最后一个肯定赋值为0
dpr[prices.length - 1] = 0;
int maxI = prices.length - 1;
System.out.print("dpr[" + (prices.length - 1) + "]=0, ");
for (int i = prices.length - 2; i >= 0; i--) {// 从右到左扫描一遍填充dpr数组,和从左边扫描一样
if (prices[i] < prices[i + 1]) {
dpr[i] = Math.max(prices[maxI] - prices[i], dpr[i + 1]);
} else {
dpr[i] = dpr[i + 1];
if (prices[i] > prices[maxI]) {
maxI = i;
}
}
System.out.print("dpr[" + i + "]=" + dpr[i] + ", ");
}
System.out.println();
int res = 0;
for (int i = 0; i < prices.length - 1; i++) { // 比较得出最大值
res = Math.max(dpl[i] + dpr[i], res);
System.out.println("dpl[" + i + "]=" + dpl[i] + ",dpr[" + i + "]="
+ dpr[i] + ",res=" + res);
}
return res;
}
}