为Project Euler提供更高效的解决方案

时间:2010-07-28 19:05:46

标签: java prime-factoring

最初,我在使这段代码运行时遇到了一些问题,但经过一些调整后我调试了它并准备好了。

我已经对这个程序进行了几次修改。我开始使用整数值只是为了发现数字太大而不适合int。然后我改为BigIntegers,这被证明是一个麻烦,但可行。从那里,我切换到longs(从一开始就应该这样做)并将我的代码的运行时间缩短8倍(或更多)。

以下是现在的代码:

long qNum = 600851475143L;

for (long i = qNum - 1L; i * i >= qNum; i -= 2L)
    if (qNum % i == 0 && isPrime(i)) {
        System.out.println("Solution:" + i); // for debugging
        return i;
    }
    else
        System.out.println(i);// for debugging

return 0L;

public static boolean isPrime(long num) {
    // unnecessary if statement for this problem (b/c of for loop), but useful for others 
    if (num % 2 == 0)
        return false;

    for (long i = 3; i * i <= num; i += 2)
        if (num % i == 0)
            return false;

    return true;
}

它已经运行了几个小时但仍然没有找到任何东西。我在网上看到解决这个难题的典型方法就像分析560GB的数据= /。

有关提高速度的提示吗?

非常感谢,

瑞斯蒂昂

修改

优化代码:

public static long greatestPrimeFactor(ArrayList<Long> factors, long num) {
    for (long i = 2; i <= Math.sqrt(num); i++) {
        if (num % i == 0) {
            factors.add(i);
            return greatestPrimeFactor(factors, num / i);
        }
    }

    for (int i = factors.size()-1; i > 0; i--)
        if (isPrime(factors.get(i)))
            return num;

    return 0;
}

public static boolean isPrime(long num) {
if (num % 2 == 0)
    return false;

for (long i = 3; i * i <= num; i += 2)
    if (num % i == 0)
        return false;

    return true;
}

运行

greatestPrimeFactor(new ArrayList<Long>(), 600851475143L);

4 个答案:

答案 0 :(得分:3)

我的解决方案在不到百分之一秒内完成。每次找到数字的除数时,将该数除以该除数,然后重新开始。你除以的最高数字是你的目标。

答案 1 :(得分:3)

你做了太多不必要的事情。这是一个更简单的解决方案:

long greatestFactor(long n) {
    long p = 0;
    for (long k = 2; k * k <= n; k++)
        while (n % k == 0) {
            n /= k;
            p = k;
        }
    if (n > 1)
        p = n;
    return p;
}

答案 2 :(得分:0)

您无需测试每个数字是否为素数。你看到了这一点,所以你只测试每个ODD号(好吧,2)。你可以进一步!快速构建一个包含前几百万个素数的表,并且仅针对这些表进行测试。你的开销会很快,但开销会很快。

编辑:这就是我所说的。这很简单。请注意我如何仅将值与已计算的素数进行比较。一旦你计算了相当数量(例如,前10000000个素数),你就会开始根据+2方法进行搜索。请记住,他们中的大多数都会被提前抓住,因为你正在跳过不必要的数字。您不需要测试15,25,35,45,55等,因为您已经测试过5.这本身就会剔除大约20%的测试,这很容易解释计算的开销。前几百万个数字。

示例输出

C:\files\j\misc>java sandbox2
resized to 200
resized to 400
resized to 800
resized to 1600
resized to 3200
resized to 6400
resized to 12800
resized to 25600
resized to 51200
resized to 102400
resized to 204800
resized to 409600
resized to 819200
664579 primes in 18 seconds. Last prime was 9999991

C:\files\j\misc>

示例代码:

public class sandbox2 {
    static int[] primes = new int[100]; // where the primes really are
    static int count = 0;
    static long mostRecentPrime;

    public static void main(String[] args) throws Exception {
        addPrime(2); // give it a couple to start
        addPrime(3);
        addPrime(5);
        long start = System.currentTimeMillis();
        for(long i = 7; i < 10000000; i++) { // all primes less than 10M
            if(isPrime(i)) addPrime(i);            
        }        
        long end = System.currentTimeMillis();
        long time = (end-start) / 1000;
        System.out.println(count + " primes in " + time + " seconds. Last prime was " + mostRecentPrime);
    }    
    public static boolean isPrime(long i) {
        long max = (long)(Math.sqrt(i))+1;
        for(int pos = 0; primes[pos] < max && pos < primes.length; pos++) {
            long prime = (long)(primes[pos]);
            if(i % prime == 0) return false;
        }
        return true;
    }    
    public static void addPrime(long p) {
        mostRecentPrime = p;
        if(count == primes.length) { // resize if necessary
            int size = primes.length * 2;
            int[] newprimes = new int[size];
            System.arraycopy(primes, 0, newprimes, 0, primes.length);
            primes = newprimes;
            System.out.println("resized to " + primes.length);
        }
        primes[(int)count] = (int)p;
        count++;
    }
}

答案 3 :(得分:0)

在python中,你可以只计算所有素因子,然后使用max函数,如下所示:

def calc_prime_factors(n,i=2,result=[]):
  while i<=n:
    while n%i!=0:
      i+=1
    result.append(i)
    if n!=1:
      n,i=n/i,2
    else:
      break
  return result

print max(calc_prime_factors(600851475143))
相关问题