如何删除:java.lang.OutOfMemoryError

时间:2015-11-19 07:06:47

标签: java algorithm dynamic-programming

我正在解决这个问题(在下面用解决方案(包括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);
}
}

1 个答案:

答案 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;