Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使这个Java代码段更高效?_Java_Algorithm - Fatal编程技术网

如何使这个Java代码段更高效?

如何使这个Java代码段更高效?,java,algorithm,Java,Algorithm,在一次计算机竞赛中,我遇到了一个必须处理输入数据的问题。输入已拆分为一个数组,其中数据[0]是重复次数。最多可重复10^18次。我的程序在线程“main”java.lang.OutOfMemoryError:java堆空间中返回了异常,我没有通过竞赛 下面是一段消耗内存和CPU的代码: long product[][]=new long[data[0]][2]; product[0][0]=data[1]; product[0][1]=data[2]; for(int a=1;a<data

在一次计算机竞赛中,我遇到了一个必须处理输入数据的问题。输入已拆分为一个数组,其中数据[0]是重复次数。最多可重复10^18次。我的程序在线程“main”java.lang.OutOfMemoryError:java堆空间中返回了
异常,我没有通过竞赛

下面是一段消耗内存和CPU的代码:

long product[][]=new long[data[0]][2];
product[0][0]=data[1];
product[0][1]=data[2];
for(int a=1;a<data[0];a++){
  product[a][0]=((data[5]*product[a-1][0] + data[6]) % data[3]) + 1; // Pi = ((A*Pi-1 + B) mod M) + 1 (for all i = 2..N)
  product[a][1]=((data[7]*product[a-1][1] + data[8]) % data[4]) + 1; // Wi = ((C*Wi-1 + D) mod K) + 1 (for all i = 2..N)
}
我的程序最多只能运行7或8位数字,然后运行需要几分钟。它有18位数字,几乎在我在Eclipse中单击“Run”时就崩溃了

我很好奇,在一台普通的计算机上怎么可能处理这么多的数据。如果我的问题不清楚或您需要更多信息,请告诉我。谢谢

long product[][]=new long[data[0]][2];
这是您粘贴的代码中唯一分配内存的行。您分配的数组的长度将是
data[0]
长度!随着数据的增长,阵列也会随之增长。你想用什么公式

您提供的第一个输入数据:

980046644627629799
已太大,甚至无法为其声明数组。尝试创建一个一维数组,将其作为其长度,然后看看会发生什么

你确定你不只是想要一个1 x 2的矩阵吗?清楚地解释你想要的算法,我们可以帮助你找到一个更优化的解决方案

这是您粘贴的代码中唯一分配内存的行。您分配的数组的长度将是
data[0]
长度!随着数据的增长,阵列也会随之增长。你想用什么公式

您提供的第一个输入数据:

980046644627629799
已太大,甚至无法为其声明数组。尝试创建一个一维数组,将其作为其长度,然后看看会发生什么


你确定你不只是想要一个1 x 2的矩阵吗?清楚地解释您想要的算法,我们可以帮助您找到一个更优化的解决方案。

您不可能也不需要一个如此长的数组。您只需要跟踪最新的值。例如,只有产品1和产品2

此外,在每次迭代后,考虑两个数是否为一个Na。如果是这样,抛出异常并给出迭代编号。


因为一旦你得到一个NaN,他们都会是NaN。除非你用的是长的,所以把它擦掉。“无所谓”。-)

你不可能也不需要这么长的数组。您只需要跟踪最新的值。例如,只有产品1和产品2

此外,在每次迭代后,考虑两个数是否为一个Na。如果是这样,抛出异常并给出迭代编号。


因为一旦你得到一个NaN,他们都会是NaN。除非你用的是长的,所以把它擦掉。“无所谓”。-)

让我们来透视一下这些数字

内存:一个
long
需要8个字节。1018
long
s占用16000000 TB。太多了

时间:10000000次操作≈ 1秒。1018步≈ 30世纪。也太多了

您可以通过意识到在任何时候只需要最新的值以及整个阵列是冗余的来解决内存问题:

long currentP = data[1];
long currentW = data[2];
for (int a = 1; a < data[0]; a++)
{
    currentP = ((data[5] * currentP + data[6]) % data[3]) + 1;
    currentW = ((data[7] * currentW + data[8]) % data[4]) + 1;
}
long currentP=data[1];
长电流w=数据[2];
对于(int a=1;a
解决时间问题有点棘手。由于使用了模数,您可以观察到数字必须在某个点输入一个循环。一旦找到循环,就可以预测n次迭代后的值,而无需手动执行每次迭代

查找周期的最简单方法是跟踪是否访问了每个元素,然后遍历,直到遇到以前见过的元素。在这种情况下,所需的内存量与M和K成正比(数据[3]和数据[4])。如果它们太大,则必须使用更节省空间的循环检测算法

下面是一个查找p值的示例:

public static void main(String[] args)
{
    // value = (A * prevValue + B) % M + 1

    final long NOT_SEEN = -1; // the code used for values not visited before

    long[] data = { 980046644627629799L, 9, 123456, 18, 10000000, 831918484, 451864686, 840000324, 650000765 };
    long N = data[0];   // the number of iterations
    long S = data[1];   // the initial value of the sequence
    long M = data[3];   // the modulus divisor
    long A = data[5];   // muliply by this
    long B = data[6];   // add this
    int max = (int) Math.max(M, S);     // all the numbers (except first) must be less than or equal to M
    long[] seenTime = new long[max + 1];    // whether or not a value was seen and how many iterations it took

    // initialize the values of 'seenTime' to 'not seen'
    for (int i = 0; i < seenTime.length; i++)
    {
        seenTime[i] = NOT_SEEN;
    }

    // find the cycle
    long count = 0;
    long cycleValue = S;    // the current value in the series
    while (seenTime[(int)cycleValue] == NOT_SEEN)
    {
        seenTime[(int)cycleValue] = count;
        cycleValue = (A * cycleValue + B) % M + 1;
        count++;
    }

    long cycleLength = count - seenTime[(int)cycleValue];
    long cycleOffset = seenTime[(int)cycleValue];

    long result;

    if (N < cycleOffset)
    {
        // Special case: requested iteration occurs before the cycle starts
        // Straightforward simulation
        long value = S;
        for (long i = 0; i < N; i++)
        {
            value = (A * value + B) % M + 1;
        }
        result = value;
    }
    else
    {
        // Normal case: requested iteration occurs inside the cycle
        // Simulate just the relevant part of one cycle
        long positionInCycle = (N - cycleOffset) % cycleLength;
        long value = cycleValue;
        for (long i = 0; i < positionInCycle; i++)
        {
            value = (A * value + B) % M + 1;
        }
        result = value;
    }

    System.out.println(result);
}
publicstaticvoidmain(字符串[]args)
{
//值=(A*prevValue+B)%M+1
final long NOT_SEEN=-1;//用于以前未访问过的值的代码
长[]数据={98004644627629799L,9123456,1810000000,831918484,451864686,840000324,650000765};
long N=data[0];//迭代次数
long S=data[1];//序列的初始值
长M=数据[3];//模除数
long A=data[5];//由这个
long B=data[6];//添加这个
int max=(int)Math.max(M,S);//所有数字(第一个除外)必须小于或等于M
long[]seenTime=new long[max+1];//是否看到值以及迭代次数
//将“seenTime”的值初始化为“not seen”
for(int i=0;i