为什么这个程序运行得这么慢?

时间:2014-05-29 18:19:44

标签: java performance

这是针对项目欧拉问题14。

当数字是偶数时,你应该将数字除以2,但是当它是奇数时,你将它乘以3并加1。最终它应该达到一个。

我的任务是找到获得最大步数的数字。

这是我的代码:

    int currentNum = 0;
    int iterator = 0;
    int[] largestChain = new int[]{0,0};
    for(int i = 10;i<=1000000;i++)
    {
        currentNum = i;
        iterator = 0;
        while(currentNum!=1)
        {
            iterator++;
            if(currentNum%2==0)
            {
                currentNum/=2;
            }
            else
            {
                currentNum = (currentNum*3)+1;
            }
        }
        if(iterator>largestChain[1])
        {
            largestChain[0] = i;
            largestChain[1] = iterator;
        }
    }

    System.out.println("largest iterator:"+largestChain[1]+"for num:"+largestChain[0]);

请告诉我什么放慢了速度,请帮助我? (它现在花了> 30分钟,它仍然没有得到答案)。

3 个答案:

答案 0 :(得分:3)

使用long个变量代替intcurrentNum变得如此之高,价值观会变成负数!

一旦你做了这个改变,你的算法就可以了。 (我测试了它)

答案 1 :(得分:0)

花费这么长时间的原因是你在100万个数字的循环操作中执行此操作。解决方案是创建一个动态保存步骤数的算法。

int[] steps = new int[1000000];
steps[0] = 0;
steps[1] = 1;

迭代完其余的数字,再加上这个基本案例。最后,您的许多路径将被计算,您将不需要嵌套循环。


但是,如果你想坚持自己的方式: 我建议在那里放一些调试打印语句,看看它在哪里被捕获。我的猜测是1百万循环而声明是罪魁祸首,但最简单的方法就是进度检查。

尝试在while之前添加System.out.println(i+":");,在while内添加System.out.println(" current number: "+currentnum);

应打印出类似的内容:

1:
     1
2:
     2
     1

答案 2 :(得分:0)

我修改了代码以打印有趣的信息以及它的循环方式。循环很疯狂。 我建议将currentNum转换为&#39; long&#39;并重新运行它,因为该数字变为负数(超出int容量)。

public class TestLoop{
public static void main(String[] args){
int currentNum = 0;
int iterator = 0;
int[] largestChain = new int[]{0,0};
for(int i = 10;i<=1000000;i++)
{
    currentNum = i;
    iterator = 0;
    System.out.println("\nCurrently Running :" + i);
    while(currentNum!=1)
    {
        iterator++;
        if(currentNum%2==0)
        {
            currentNum/=2;
        }
        else
        {
            currentNum = (currentNum*3)+1;
        }
            System.out.print(currentNum + " ");
    }
    if(iterator>largestChain[1])
    {
        largestChain[0] = i;
        largestChain[1] = iterator;
     }
  }

System.out.println("\nLargest iterator: "+largestChain[1]+" for num:"+largestChain[0]);
 }
}

我在linux上运行它,并在将currentNum更改为“长”后的10分钟内得到了以下答案。

最大迭代器:524 for num:837799

你的逻辑中还有一个缺陷:你不会检查是否有其他数字采用相同的迭代。例如。下面的循环给出了两个这样的数字:

import java.util.ArrayList;
public class TestLoop {
public static void main(String[] args) {
    long currentNum;
    int iterator;
    int[] largestChain = new int[]{0, 0};
    ArrayList Nums = new ArrayList();
    for (int i = 10; i <= 300; i++) {
        currentNum = i;
        iterator = 0;
        System.out.println("\nCurrently Running :" + i);
        while (currentNum != 1) {
            iterator++;
            if (currentNum % 2 == 0) {
                currentNum /= 2;
            } else {
                currentNum = (currentNum * 3) + 1;
            }
            System.out.print(currentNum + " ");
        }
        if (iterator > largestChain[1]) {
            largestChain[0] = i;
            largestChain[1] = iterator;
            Nums.clear();
            Nums.add(i);
        } else if (iterator == largestChain[1]) {
            Nums.add(i);
        }
    }

    System.out.println("\nLargest iterator: " + largestChain[1]);
    //+ " for num:" + largestChain[0]);
    if (Nums.size() == 1) {
        System.out.println("There is only one number with " + largestChain[1] + " iterations:" + largestChain[0]);
    } else {
        System.out.print("Below numbers took " + largestChain[1] + " iterations:");
        for (int i = 0; i < Nums.size(); i++) {
            System.out.print(" " + Nums.get(i));
        }
    }

 }
}