我被要求将除1之外的因子和数组中每个数字的数字本身相加。问题是它必须能够处理非常大的数组,并且对于大小为100,000,000的数组,我当前的实现需要很长时间。我计算每个数字因子的代码是
static long countFactors(long num){
long count=0;
long max =(long) Math.floor(Math.sqrt(num));
for(int i=2; i<=max;i++){
if(num%i==0&&(i*i)!=num){
// count i and n/i as a factor
count+=2;
if(num/i<max){
max=num/i;
}
}
else if(num%i==0){
// just add one factor since it is the numbers root.
count+=1;
}
}
return count;
}
有没有人有任何优化建议。
答案 0 :(得分:2)
我在这篇文章的开头就提出了最好的想法:
可被n
整除的数字可被n
的所有因素整除。
也许这是降低时间复杂度的关键。剩下的就是:
现在只需执行一次即可执行测试(i*i)!=num
O(max)次。 (for(int i=2; i**<**max;i++)
然后检查平方根)。你确实说过非常大的数字,所以这可以节省一点。
这又是什么? if(num/i<max){
max=num/i;
}
如果我正确阅读,这是多余的。此循环中的因子i
绝不会超过num
的平方根。
最后,在空间允许的情况下,您可以将外部循环放在i
上,将循环放在内部的数组中。通过不需要重复i*i
,这将节省一点点。这些只是对当前算法的微优化。
答案 1 :(得分:1)
很难回答这个问题,因为很难确切地知道问题是什么。一些评论如下。如果问题得到澄清,我可能会给出更好的答案。
1)目前尚不清楚你是否想要数字 n 的不同素数因子,具有多重性的素数因子或数字的除数。例如,给定数字 n = 12,不同的素数因子是2和3,其多重性的素因子是2,2和3,除数是1,2,3,4你的程序回答了关于除数的问题,所以我认为这就是你想要的,但你也提到你要从列表中消除1和 n ,这是不寻常的。
2)在不同的时间,你提到因素的计数和因子的总和。请准确说明你想要的东西。
3)目前尚不清楚您是否正在处理长度为10 ^ 8或 n 大到10 ^ 8的数组。如果你的数组长度为10 ^ 8,那么无论你做什么都需要一段时间。如果你有一个小得多的数组,比如一千个数字 n ,每个小于10 ^ 8,这就变得简单得多了。
假设你想要除数,这是一个函数,它将 n 的因子与它们的多重性相对应,并返回 n 的除数的和与计数。如果需要,您可以从计数中减去2,从总和中减去 n +1,以排除1和 n :
function divSumCount(n)
mult, sum, count, prev := 2, 1, 1, 0
for fact in sort(factors(n))
if fact == prev
mult := mult + 1
else if prev <> 0
sum := sum * (prev ** mult - 1) / (prev - 1)
count := count * mult
mult := 2
prev := fact
sum := sum * (prev ** mult - 1) / (prev - 1)
count := count * mult
return sum, count
这是伪代码,我将留给你翻译成Java。假设 n 不大于10 ^ 8,这里有一个简单的程序,它使用试验除法计算 n ,返回按递增顺序排序的因子;如果 n 较大,您需要一个更好的算法来查找其因素:
function factors(n)
f, fs := 3, []
while n % 2 == 0
append 2 to fs
while f * f <= n
while n % f == 0
append f to fs
n := n / f
f := f + 2
if n > 1 append n to fs
return fs
4)如果数字 n 在数组中是连续的,例如从54813000到54823000,你可以筛选因子而不是费力地分解每个 n ,这将是要快得多。
如果您需要更多信息,请与我们联系。
答案 2 :(得分:0)
CAVEAT EMPTOR:这是一个我没有用基准测试的想法,所以它可能不是一个好的解决方案。
对于单个数字,您的代码非常好。但是如果你必须找到许多数字的因素,那么找到主要因素是一个很好的解决方案。
我的想法就像这样
1)从列表中找到您必须处理的最大数字(最大值)。
2)找到介于1和最大/ 2之间的素数(这是困难的部分,但只进行一次)。
3)你分析素数因子中的每个数字,例如。 150是2 * 3 * 5 * 5
4)所有因素都是素数因子的组合,在这种情况下它们是
*)2
*)2 * 3 = 6
*)2 * 5 = 10
*)2 * 3 * 5 = 30
*)2 * 5 ^ 2 = 50
*)3
*)3 * 5 = 15
*)3 * 5 ^ 2 = 75
*)5
*)5 ^ 2 = 25
优点是你只检查质数,这只是数字的一部分(如果你的数字变大,则减少一个)。无效是计算非素因子的最后一步,以及计算素数的时间(和记忆)(尽管你可能会将它们预先计算并存储在文件中一定的大小)。
答案 3 :(得分:0)
我可能会后悔这一点,但我会试一试。我假设你有足够的RAM /交换,并且更担心计算时间。我也假设你真的想要主要因素,而不是所有因素。
我要做的第一件事是对数组进行排序并确定唯一值。然后,我将尝试使用数组sieve
构造Sieve of Eratosthenes,以识别(排序)唯一值数组中最大值的平方根的所有素数。我还会将所有数字的并行数组保持为最大值,将其称为sum_array
,并将其初始化为全零。当我逐步通过sieve
数组来屏蔽当前值的所有倍数时,我也会在相同的索引处逐步执行sum_array
并将当前素数添加到并行的每个元素的运行总计中屏蔽sieve
数组中该素数的倍数。
由于我真的不知道这是为了什么,所以我已经完成了除此之外的建议。