我编写了一个JAVA程序,它几乎不需要3-4 MB的内存,但仍然不知何故超过了我提交判断问题的分级器上的16 MB内存限制。
我有一个大小为2500 * 100的整数2D数组,占用大约1 MB,以及一个最多有2500个节点和2499个边(Tree)的邻接列表。
为什么它超过16 MB的内存限制?我知道JAVA有一些开销,但我仍然无法理解为什么它超出了限制。如果有人可以解释为什么代码消耗这么多内存的原因,那将对我有很大的帮助。我也在做DFS,它会消耗一些堆栈内存,但没有理由超过16 MB限制。
以下是代码:
import java.io.*;
import java.util.*;
class CateringContracts2pi
{
static ArrayList<ArrayList<Integer>> adj = new ArrayList<ArrayList<Integer>>(2505);
static int mod = 10243;
static int ans=0;
static int dp[][]=new int[2501][101];
static int temp[]=new int[101];
static int N,K;
public static void main(String[]args)
{
Scanner sc = new Scanner(System.in);
for(int i=0;i<2505;i++)
adj.add(new ArrayList<Integer>());
N = sc.nextInt();
K = sc.nextInt();
for(int i=1;i<N;i++)
{
int u = sc.nextInt();
int v = sc.nextInt();
adj.get(u).add(v);
adj.get(v).add(u);
}
for(int i = 1; i <= N; i++)
{
dp[i][0] = dp[i][1] = 1;
}
dfs(1,0);
System.out.println(ans);
}
static void dfs(int node,int par)
{
int sz = adj.get(node).size();
for(int i=0;i<sz;i++)
{
int next = adj.get(node).get(i);
if(next==par)continue;
dfs(next,node);
Arrays.fill(temp,0);
for(int j=1;j<=K;j++)
{
for(int k=1;k+j<=K;k++)
{
temp[j+k]+=dp[node][j]*dp[next][k] % mod;
}
}
for(int j=1;j<=K;j++)
{
dp[node][j] += temp[j];
dp[node][j] %= mod;
}
}
ans+=dp[node][K];
ans%=mod;
}
}
答案 0 :(得分:0)
您手动输入了~2505个元素吗?我真的不羡慕你。我将您的示例修改为更友好的视图:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.ThreadLocalRandom;
class CateringContracts2pi {
private static final List<List<Integer>> adj = new ArrayList<>(2505);
private static final int mod = 10243;
private static final int dp[][] = new int[2501][101];
private static final int temp[] = new int[101];
private static int ans = 0;
public static void main(String[] args) {
long beforeUsedMem = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 2505; i++) {
adj.add(new ArrayList<>());
}
System.out.print("Enter N:");
final int N = sc.nextInt();
long afterUsedMem = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
long actualMemUsed = afterUsedMem - beforeUsedMem;
System.out.println("usage = " + actualMemUsed / 1024);
for (int i = 1; i < N; i++) {
int u = ThreadLocalRandom.current().nextInt(0, N);
// int u = sc.nextInt();
// int v = sc.nextInt();
int v = ThreadLocalRandom.current().nextInt(0, N);
adj.get(u).add(v);
adj.get(v).add(u);
}
actualMemUsed = afterUsedMem - beforeUsedMem;
System.out.println("usage = " + actualMemUsed / 1024);
for (int i = 1; i <= N; i++) {
dp[i][0] = dp[i][1] = 1;
}
actualMemUsed = afterUsedMem - beforeUsedMem;
System.out.println("usage = " + actualMemUsed / 1024);
System.out.print("Enter K:");
final int K = sc.nextInt();
dfs(1, 0, K);
System.out.println(ans);
actualMemUsed = afterUsedMem - beforeUsedMem;
System.out.println("usage = " + actualMemUsed / 1024);
}
private static void dfs(int node, int par, final int K) {
int sz = adj.get(node).size();
for (int i = 0; i < sz; i++) {
int next = adj.get(node).get(i);
if (next == par) continue;
dfs(next, node, K);
Arrays.fill(temp, 0);
for (int j = 1; j <= K; j++) {
for (int k = 1; k + j <= K; k++) {
temp[j + k] += dp[node][j] * dp[next][k] % mod;
}
}
for (int j = 1; j <= K; j++) {
dp[node][j] += temp[j];
dp[node][j] %= mod;
}
}
ans += dp[node][K];
ans %= mod;
}
}
我设置了-Xmx4m
JVM设置并使用不同的输入参数运行它 - 我得到的所有内容都是java.lang.StackOverflowError
。这个异常与内存使用没有任何关系,我的意思是堆内存。您可以通过-Xss
参数设置堆栈大小,但我认为您需要重构您的dfs方法。
关于堆内存使用我们可以说些什么?我们来算一下:
Integers
列表(2501 * 16 + 16)* 101 = 3,9Mb 因此,对于数据,我们有~5Mb(填充所有列表列表时的最大值),对于JVM,我们有1Mb。就是这样。
答案 1 :(得分:-1)
JVM本身设置了它将使用多少内存。以下提示可以为您提供帮助:How is the default java heap size determined?。您可以尝试使用-Xmx,-Xms等标志来减少已用内存量。