这是我为问题5项目Euler寻找性能良好的算法的尝试-找到均匀可分x的小号可能数和x以下的所有数。
我尝试使用一个循环使#s和另一个循环来测试该数字是否可以被x和x以下的所有#s整除
System.out.println("This program finds the smallest positive "
+ "number that");
System.out.println("is evenly divisible by all of the numbers "
+ "from 1 to N.");
System.out.print("Enter N: ");
int N=kb.nextInt();
long bigN=1;
for(int i=1;i<=N;i++){
bigN=bigN*i;
/*bigN serves as a definite end for our loop
when trying to find all #s divisible from 1 to n
*/
}
long smallestAnswer=bigN;
int count=0;
for(long i=1;i<=bigN;i++){//# being tested
for(int j=1;j<=N;j++){//test
if(i%j==0){
count++;
}
if(count==N && i<smallestAnswer){
smallestAnswer=i;//should catch only the first/smallest answer
break;
}
}
count=0;
}
System.out.printf("\nThe smallest # evenly divisible by all of the "
+ "numbers from 1 to N");
System.out.printf("\nis %,d\n",smallestAnswer);
}
该代码有效。没有运行/编译时间错误。太慢了。如果用户输入的#大于11,则代码基本上会冻结
答案 0 :(得分:5)
您正在使用蛮力算法。就像在Euler项目上发现的那样,挑战通常是寻找正确算法的挑战,而不仅仅是编写代码的挑战。
这里的挑战是要找到从1到X的所有数字中的最小公倍数(请参见Wikipedia)。
示例:如果X为10,解决它的一种方法是确定除数:
1 = 1
2 = 2
3 = 3
4 = 2^2
5 = 5
6 = 2 * 3
7 = 7
8 = 2^3
9 = 3^2
10 = 2 * 5
因此,最小公倍数的除数为:
1 * 2^3 * 3^2 * 5 * 7 = 1 * 8 * 9 * 5 * 7 = 2520
由于这是您要解决的挑战,因此我将把编码留给您。
答案 1 :(得分:1)
我不太确定您为什么要为性能而苦苦挣扎。
$ date && X 20 && date
Tue Jun 25 13:18:13 CDT 2019
N: 20
232792560 is divisible by all numbers 1 to 20
Tue Jun 25 13:18:16 CDT 2019
3秒(N == 20)。
您要为每个检查的数字做额外的数学运算-很多额外的数学运算。首先,您可以从2到N,而不是对从1到N的每个数字进行检查,因为所有数字都可以被1整除。但是更重要的是,即使一个数字失败,您也将执行ALL。如果您转过这一部分,则在模数检查失败后就会中断“此数字是否起作用”代码。在N = 20时,这将为您节省18个对所有奇数的校验。
您还可以获得更多改进。该数字必须是偶数。因此,如果n> 1,则可以从2开始并以2而不是1递增。如果n> = 3,则实际上可以从6开始,然后增加6,从而节省了大量数学运算。如果n> = 4,则可以从12开始,再增加12。
作为参考,这是我的实现。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int n = atoi(argv[1]);
long trying = 1;
bool found = false;
while(!found) {
found = true;
++trying;
for (long checkDivide = 2; checkDivide <= n; +checkDivide) {
if (trying % checkDivide != 0) {
found = false;
break;
}
}
}
printf("%ld is divisible by all numbers 1 to %d\n", trying, n);
return 0;
}
我跳过了输入请求,只是将值放在命令行上。
请注意,逆转检查也可能更有效。也就是说,从n开始检查并降低到2。X%20的失败率要比X%2更高。我没有使用足够的时间检查分辨率来确保效率更高。