【问题标题】:Optimal algorithm for smallest possible number evenly divisible by all numbers below X [closed]可被 X 以下的所有数整除的最小可能数的最优算法 [关闭]
【发布时间】:2019-06-25 17:49:55
【问题描述】:

这是我为问题 5 Project 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 的#,代码就基本冻结了

【问题讨论】:

  • 我投票决定将此问题作为离题结束,因为要求改进运行代码的问题属于 codereview.stackexchange.com
  • @Andreas 我不同意。这是纯粹的算法。这不是一个简单的代码审查问题。
  • 在哪里:比这里的帮助台学习 codereview 帮助台要多得多。了解如何提出社区范围内的问题。
  • @AlexandarPetrov 如果有关于算法的问题,请使用Computational Science Stack Exchange
  • @GhostCat 通过提供示例解决方案,他已经证明他已经做出了努力。

标签: java algorithm performance


【解决方案1】:

您正在使用蛮力算法。挑战,就像在 Project 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

既然这是你要解决的挑战,我就把编码留给你。

【讨论】:

    【解决方案2】:

    我不太清楚您为什么在性能方面遇到问题。

    $ 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
    

    N == 20 为 3 秒。

    您检查的每个数字都在做额外的数学运算——很多额外的数学运算。首先,您可以从 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 更频繁地失败。我没有使用足够的时间检查分辨率来确定它的效率有多高。

    【讨论】:

    • 非常感谢。我刚刚重新编写了我的代码,但这次我使用了布尔值和中断,我很快就得到了答案。我在这个线程中读到的内容是正确的,这不仅仅是为了找到正确的答案。它是关于高效地完成它并删除所有额外的数学,使我的代码更有效率。再次感谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-13
    • 1970-01-01
    • 1970-01-01
    • 2016-11-19
    • 2022-12-19
    • 1970-01-01
    • 2011-09-11
    相关资源
    最近更新 更多