我正在解决这个问题(在下面用解决方案(包括dp)说明),我收到了java.lang.OutOfMemoryError错误。我已经知道dp删除了不必要的计算,所以我也应用了dp,但是为什么我得到这个错误我们能比dp优化得更好吗?或者我做错了,因为解决方案运行的是小输入?
问题陈述
您的算法在预测市场方面已经非常擅长,您现在知道了未来N天内Wooden Orange Toothpicks Inc.(WOT)的股价。
每天,您可以购买一股WOT,出售您拥有的任意数量的WOT股票,或者根本不进行任何交易。通过最佳交易策略可以获得的最大利润是多少?
输入
第一行包含测试用例的数量T.T测试用例如下:
每个测试用例的第一行包含一个数字N.下一行包含N个整数,表示未来N天WOT股票的预测价格。
输出
输出T行,包含相应测试用例可获得的最大利润。
约束
1&lt; = T&lt; = 10 1 <= N <= 50000
所有股价介于1至100000之间
我的解决方案
import java.util.Arrays;
import java.util.Scanner;
public class Stock_Maximize {
private static int days;
private static long[] a;
private static int t;
private static long[][] dp;
// private static int max;
public static void main(String args[]) {
Scanner e = new Scanner(System.in);
t = e.nextInt();
while (t > 0) {
days = e.nextInt();
int m = days;
// System.out.println(days);
int i = 1;
a = new long[days + 1];
while (m > 0) {
a[i] = e.nextInt();
i++;
m--;
}
dp = new long[days + 1][days + 1];
for (int k = 0; k < days + 1; k++) {
Arrays.fill(dp[k], -1);
}
System.out.println(solve(1, 0));
t--;
}
}
private static long solve(int daynumber, int stocks) {
// TODO Auto-generated method stub
// System.out.println("vefvvv");
long x;
int i = 1;
if (daynumber == (days + 1)) {
// System.out.println("daynumber= " + daynumber);
return 0;
}
if (stocks < 0) {
// System.out.println("***********");
return 0;
}
if (dp[daynumber][stocks] != -1) {
return dp[daynumber][stocks];
}
long z = solve(daynumber + 1, stocks + 1) - a[daynumber];
// System.out.println("z= " + z);
long m = solve(daynumber + 1, stocks);
int d = stocks;
long max = Long.MIN_VALUE;
while (d > 0) {
d = stocks - i;
x = solve(daynumber + 1, d) + i * a[daynumber];
i++;
// System.out.println("x= " + x + "z= " + z + "m= " + m);
if (max < getmax(x, z, m)) {
max = getmax(x, z, m);
}
}
dp[daynumber][stocks] = Math.max(max, Math.max(z, m));
return dp[daynumber][stocks];
}
private static long getmax(long x, long z, long m) {
// TODO Auto-generated method stub
return Math.max(Math.max(x, z), m);
}
}
答案 0 :(得分:1)
正如评论中提到的,对于您的50000*50000*64
表,您使用的是long[][]dp
位内存(n
),大约为20 GB,对于任何个人而言都太大了计算机。
问题可以通过更简单的方式解决。
对于i
天的集合,假设在i - 1
天,我们拥有WOT的最大价格,因此,为了获得最大的利润,我们需要从第0天到第天{WOT'购买WOT {1}},并在i
天出售所有这些内容。从i + 1
开始,我们可以遵循相同的策略,这将为我们带来最大的利润。
如果正确实施,此解决方案的空间复杂度为 O(n),时间复杂度为 O(n log n)。
的伪代码:
class WOT{
int day;
int price;
}
WOT[]data = new WOT[n];
//Initialize data here
long[]cost = new long[n];
for(int i = 0; i < n; i++)
cost[i] = data[i].price + (i > 0 ? cost[i - 1] : 0);
sort data based on price
int startDate = 0;
long result = 0;
for(int i = n - 1; i >= 0; i--){
if(data[i].day > startDate){
int numberOfDays = data[i].day - startDate;
result += numberOfDays*data[i].price - (cost[data[i].day - 1] - cost[startDate - 1])
startDate = data[i].day + 1;
}
}
print result;