我试图找到数字600851475143的最大素数因子并成功使用下面的代码,但我知道这是一种残酷的力量方式,并且可能有更有效和更优雅的方法来解决这个问题。但是,我想不出任何立即,并希望有人可以分享他们的解决方案的解释。
public class Solution {
// find prime numbers
ArrayList<Long> primelist = new ArrayList<>();
ArrayList<Long> findPrime(Long num) {
for (Long i = Long.valueOf(2); i <= num; i++) {
if (num % i == 0) {
primelist.add(i);
num = num / i;
if (num == 1) {
break;
}
}
}
System.out.println(primelist);
return primelist;
}
public static void main(String[] args) {
Solution sol = new Solution();
sol.findPrime(Long.valueOf(600851475143L)); // [71, 839, 1471, 6857]
}
}
答案 0 :(得分:2)
如果您尝试分解的数字是两个大素数的乘积,则因子分解在计算上是昂贵的。但是,您的算法(正如您所观察到的)效率特别低。
您的算法被称为试验分区,并且您已经编写了O(N)。它可以很容易地改进为最坏情况 O(N 0.5 )算法;见下文。
本维基百科页面总结了许多不同难度的算法:见https://en.wikipedia.org/wiki/Integer_factorization。
分解任意非素数的问题已知在NP中并且怀疑不在P中:见https://en.wikipedia.org/wiki/NP_(complexity)#Formal_definition。
以下是一些加速程序的简单方法:
请勿使用Long
进行计算。请改用long
。您的代码将生成并垃圾收集大量Long
个对象。
使用试用版来对数字n
进行因子分解时,您可以在到达sqrt(n)
时停止寻找素数因素。
当您找到素数因子时,您可以通过将原始数除以因子来加速因子分解,然后尝试将结果分解。 (事实上,你已经这样做了。)
(但与更复杂的算法相比,这是“鸡饲料”。)