我正在尝试将列表划分为尽可能大的子列表。如果列表不能以这种方式划分,我将根据需要处理它,但我需要获得除N本身之外的最大数量,均匀地划分N.
我写了一个非常天真的解决方案,但我觉得应该有一个公式或者其他东西可以在不变的时间内完成。我的列表不是那么大,最大大小是1000.这可能不是关键路径,但有更好的算法吗?
public static int largestDivisor(int n){
int divisor = 0;
for (int i = 1; i <= n/2; i++)
if (n % i == 0)
divisor = i;
return divisor;
}
答案 0 :(得分:4)
反向迭代值。只需返回您找到的第一个(它将是最好的)。像,
public static int largestDivisor(int n) {
for (int i = n / 2; i >= 2; i--) {
if (n % i == 0) {
return i;
}
}
return 1;
}
或者,您可能会对@WillemVanOnsem的answer进行略微改进,并以奇数值开头,例如;
public static int largestDivisor(int n) {
if (n % 2 == 0) {
return n / 2;
}
final int sqrtn = (int) Math.sqrt(n);
for (int i = 3; i <= sqrtn; i += 2) {
if (n % i == 0) {
return n / i;
}
}
return 1;
}
答案 1 :(得分:1)
你知道如果 a 可以通过 b 分割,它也可以通过 a / b 分割,而较小的 b < / em>是, a / b 越大,所以一旦找到了除数,就返回n/divisor
:
public static int largestDivisor(int n){
for(int i = 2; i <= n/2; i++)
if(n % i == 0) {
return n/divisor;
}
}
return 0; //or whatever you decide to return if there is no such divisor
}
这也更快,因为:
sqrt(n)
。所以最有效的方法是:
public static int largestDivisor(int n){
int sqrtn = (int) Math.sqrt(n);
for(int i = 2; i <= sqrtn; i++)
if(n % i == 0) {
return n/divisor;
}
}
return 0;
}
答案 2 :(得分:1)
我不知道你是否可以在不变的时间内完成这项工作,但你可以在比这更短的时间内完成这项工作。
从2开始,遍历所有数字,检查n是否可以被该数字整除。当你得到一个除以n的数字,那么你可以停止 - 你的答案是n / i。如果你走到尽头但它仍然没有分裂,那么n是素数,答案只有1。
如果你没有找到除数,而不是以n / 2结尾,你可以用这种方法结束√n,这将减少大O.
此外,您可以先检查它是否可被2整除,然后转到3并仅检查那里的奇数。 (如果它被一个偶数整除,则它可以被2整除。)它不会改变大O,但它应该将处理时间减少一半,因为你只检查了大约一半除数。