项目欧拉#14:程序运行很长时间

时间:2015-12-15 23:00:42

标签: java

我正在尝试解决Project Euler#14:

The following iterative sequence is defined for the set of positive integers:

n → n/2 (n is even)
n → 3n + 1 (n is odd)  

Using the rule above and starting with 13, we generate the following sequence:
               13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1  

Which starting number, under one million, produces the longest chain?

这是我尝试过的:

public class Problem14 {
    public static void main(String[] args) {
        int longestLength = 1;
        int longestStart = 1;
        for (int i = 1; i < 1000000; i++) {
            int candidate = getCollatzLength(i);
            if (candidate > longestLength) {
                longestLength = candidate;
                longestStart = i;
            }
        }
        System.out.println("starting point = " + longestStart);
    }

    public static int getCollatzLength(int startingNumber) {
        int length = 1;
        while (startingNumber != 1) {
            startingNumber = getNextCollatz(startingNumber);
            length++;
        }
        return length;
    }

    public static int getNextCollatz(int current) {
        if (current % 2 == 0) {
            return current / 2;
        } else {
            return 3 * current + 1;
        }
    }
}

不幸的是,这种情况持续了很长时间(超过5分钟)。知道这里出了什么问题吗?

当我打印产生当前最长链的起始编号时,我得到的最后一个是:

new longest start is 106239

3 个答案:

答案 0 :(得分:3)

当它达到113,383时,链中的元素超过2 ^ 31-1并因此超出int的范围,并且在达到一百万之前还有许多其他时间发生。它将在链中达到的最大值是56,991,483,520。如果您从int更改为long,那么您应该没问题。

答案 1 :(得分:2)

有很多冗余计算。例如,找到1,000,000的collat​​z序列的长度需要找到500,000的collat​​z序列。您应该将所有中间结果存储在数组/列表中以减少冗余。

答案 2 :(得分:0)

Try this

import java.util.*;

public class Solution {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int t = in.nextInt();

        int result = 0;
        int maxcount = 0;

        int [] arr = new int[(int) (5 * Math.pow(10, 6) + 1)];
        for(int i=2;i<=3732423;i++) {
            int count = steps(i,0);
            if(count > maxcount) {
                result = i;
                maxcount = count;
            }
            else if(count == maxcount) {
                result = i;
            }
            arr[i] = result;
        }

        for(int a0 = 0; a0 < t; a0++){
            int no = in.nextInt();

            if(no > 3732423){
                System.out.println(3732423);
            }else{
                System.out.println(arr[no]);
            }
        }
    }


    public static int steps(long num,int count) {

        while(num !=1) {
            if(num % 2 == 0) {
                count++;
                num = num / 2;
            }
            else {
                count++;
                num = num*3 + 1;
            }
        }
        return count;

    }
}