如何解决关于此代码的java.lang.OutOfMemoryError

时间:2018-12-01 17:39:15

标签: java

这是一个简单的任务,以“之字形”移动求和矩阵中的元素  按水平。变量“ sumPath”必须很长,会抛出“ java.lang.OutOfMemoryError”。

我有两个“ for”周期,需要缩短它们。

我该怎么做?

代码如下:

public static void main(String[] args) {

    Scanner scanner = new Scanner(System.in);
    int n = Integer.parseInt(scanner.next());
    int m = Integer.parseInt(scanner.next());
    int[][] matrix = new int[n][m];
    long sumPath = 1;

    matrix[0][0] = 1;
    for (int row = 0; row < n; row++) {
        if (row > 0) {
            matrix[row][0] = matrix[row - 1][0] + 3;
        }
        for (int col = 1; col < m; col++) {
            matrix[row][col] = matrix[row][col - 1] + 3;
        }
    }
    int row = 0;
    while (row < n-1) {
        for (int col = 1; col < m; col++) {
            if (col % 2 == 0) {

                sumPath = sumPath + matrix[row][col];
            } else {

                sumPath = sumPath + matrix[row+1][col];
            }
        }
        row = row + 2;
        if (row >= n) {
            break;
        }
        for (int col = m - 2; col >= 0; col--) {
            if (col % 2 == 0) {

                sumPath = sumPath + matrix[row][col];

            } else {

                sumPath = sumPath + matrix[row-1][col];

            }
        }
    }
    System.out.println(sumPath);
 }
}

2 个答案:

答案 0 :(得分:0)

只有一行代码可能会发生OutOfMemoryException:

 int[][] matrix = new int[n][m];

矩阵必须完全适合内存。当数字n和m太大时,矩阵对于可用内存将变得太大。

答案 1 :(得分:0)

肯定地,初始化数组时您拥有OutOfMemoryError

int[][] matrix = new int[n][m]

对于大nm来说,这是很烦人的(例如,默认设置为JVM,您肯定会得到n = m = 100_000的例外)。

但是请注意,您不必创建整个数组。计算路径时,仅使用有限数量的矩阵像元,并且仅在需要时才可以计算。

private static final int ZERO = 1;
private static final int OFFS = 3;

public static int get(int row, int col) {
    int val = ZERO;

    for (int i = 0; i < row; i++)
        val += OFFS;

    for (int i = 0; i < col; i++)
        val += OFFS;

    return val;
}

是的,创建矩阵会比较慢,但是绝对可以保护您免受OutOfMemoryError的侵害。为了提高速度,您可以缓存计算的值:

private static final Map<Integer, Map<Integer, Integer>> MAP = new HashMap<>();

public static int get(int row, int col) {
    Map<Integer, Integer> values = MAP.computeIfAbsent(row, k -> new HashMap<>());

    if (!values.containsKey(col)) {
        int val = ZERO;

        for (int i = 0; i < row; i++)
            val += OFFS;

        for (int i = 0; i < col; i++)
            val += OFFS;

        values.put(col, val);
    }

    return values.get(col);
}

PS 这是您的解决方案的外观:

public static void main(String... args) {
    try (Scanner scan = new Scanner(System.in)) {
        System.out.print("Height: ");
        int height = scan.nextInt();

        System.out.print("Width: ");
        int width = scan.nextInt();

        System.out.println(calcSumPath(height, width));
    }
}

private static long calcSumPath(int height, int width) {
    long sumPath = ZERO;
    int row = 0;

    while (row < height - 1) {
        for (int col = 1; col < width; col++)
            sumPath += get(col % 2 == 0 ? row : row + 1, col);

        row += 2;

        if (row >= height)
            break;

        for (int col = width - 2; col >= 0; col--)
            sumPath += get(col % 2 == 0 ? row : row - 1, col);
    }

    return sumPath;
}

private static final int ZERO = 1;
private static final int OFFS = 3;
private static final Map<Integer, Map<Integer, Integer>> MAP = new HashMap<>();

public static int get(int row, int col) {
    Map<Integer, Integer> values = MAP.computeIfAbsent(row, k -> new HashMap<>());

    if (!values.containsKey(col)) {
        int val = ZERO;

        for (int i = 0; i < row; i++)
            val += OFFS;

        for (int i = 0; i < col; i++)
            val += OFFS;

        values.put(col, val);
    }

    return values.get(col);
}