时间限制:3秒 空间限制:32768K
热度指数:899
本题知识点: 动态规划
题目描述
在股市的交易日中,假设最多可进行两次买卖(即买和卖的次数均小于等于2),规则是必须一笔成交后进行另一笔(即买-卖-买-卖的顺序进行)。给出一天中的股票变化序列,请写一个程序计算一天可以获得的最大收益。请采用实践复杂度低的方法实现。
给定价格序列prices及它的长度n,请返回最大收益。保证长度小于等于500。
测试样例:
[10,22,5,75,65,80],6
返回:
87
代码:
import java.util.*;
//比较器(无用)
class Comparators {
public static Comparator getComparator() {
return new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof Integer) {
return compare( (Integer) o1, (Integer) o2);
} else return 1;
}
public int compare(Integer s1, Integer s2) {
return s2-s1;
}
};
}
}
public class Main {
//纯暴力, 2310ms
public static int maxProfit1(int[] prices, int n) {
// write code here
int ans = 0;
//购买2次
for(int i = 0; i <= n-4; i++) {
for(int j = i+1; j <= n-3; j++) {
for(int k = j+1; k <= n-2; k++) {
for(int l = k+1; l <= n-1; l++) {
ans = Math.max(ans, prices[l]+prices[j]-prices[i]-prices[k]);
}
}
}
}
//购买1次
for(int i = 0; i <= n-2; i++) {
for(int j = i+1; j <= n-1; j++) {
ans = Math.max(ans, prices[j]-prices[i]);
}
}
return ans;
}
//DP, 73ms
public static int maxProfit(int[] prices, int n) {
// write code here
//记录i天之前(包括i天)一笔成交后的最大利润
int[] pre = new int[n+10];
//记录i天之后(包括i天)一笔成交后的最大利润
int[] post = new int[n+10];
//第0天买第0天卖
pre[0] = 0;
//记录i天之前(包括i天)股票的最低价格
int minp = prices[0];
for(int i = 1; i < n; i++) {
minp = Math.min(minp, prices[i]);
//比较在i这天卖利润高,还是i天之前卖利润高
pre[i] = Math.max(pre[i-1], prices[i]-minp);
}
//第n-1天买第n-1天卖
post[n-1] = 0;
//记录i天之前(包括i天)股票的最高价格
int maxp = prices[n-1];
for(int i = n-2; i >= 0; i--) {
maxp = Math.max(maxp, prices[i]);
//比较在i这天买利润高,还是i天之后买利润高
post[i] = Math.max(post[i+1], maxp-prices[i]);
}
//ans = max(pre[i]+post[i])(0<=i<n)
int ans = pre[0]+post[0];
for(int i = 1; i < n; i++) {
ans = Math.max(ans, pre[i]+post[i]);
}
return ans;
}
/*
测试代码
*/
public static void main(String []args){
/*
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
}
*/
int[] prices = {235,55,628,455,414,547,454};
int n = 7;
System.out.println(maxProfit(prices, n));
}
}