【问题标题】:Fixing the performance time of algorithm修复算法的执行时间
【发布时间】:2020-09-19 15:02:14
【问题描述】:

创建以下程序来计算数字的完美幂

最终结果是让 Perfect Power 在不到 0.01 秒的执行时间内完成所有测试用例。

目前,10,000 的程序最终结果时间性能约为 2 秒以上,而 1073741824 的时间性能要长得多。需要帮助以帮助将所有完美能力的时间缩短到 0.01 秒或更短。

下面是程序代码:

    /**
  
 *
 * A utlity class to calculate the perfect power of an integer
 */
public class PerfectPower {
    public static void main(String[] args) {
        new TimeExec(new Runnable() {
            public void run() {
                   System.out.println("Perfect Power of 17 is " + getPerfectPower(17));
            }
        }, "Get Perfect Power of 17", System.out).start();
        
        new TimeExec(new Runnable() {
            public void run() {
                   System.out.println("Perfect Power of 625 is " + getPerfectPower(625));
            }
        }, "Get Perfect Power of 625", System.out).start();
        
        new TimeExec(new Runnable() {
            public void run() {
                   System.out.println("Perfect Power of 1024 is " + getPerfectPower(1024));
            }
        }, "Get Perfect Power of 1024", System.out).start();
        
        new TimeExec(new Runnable() {
            public void run() {
                   System.out.println("Perfect Power of 10000 is " + getPerfectPower(10000));
            }
        }, "Get Perfect Power of 10000", System.out).start();
        
        new TimeExec(new Runnable() {
            public void run() {
                   System.out.println("Perfect Power of 1073741824 is " + getPerfectPower(1073741824));
            }
        }, "Get Perfect Power of 1073741824", System.out).start();  
    }

    /**
     * Get the perfect power for a number.
     * @param x number for which to calculate the perfect power.
     */
    public static int getPerfectPower(int x) {
        int largestP = 1;
           
        for (int b = 1; b < x; b++) {
        for (int p = 1; p < x; p++) {
           
                if (Math.pow(b,p) == x) {
                    largestP = p;
                }
           }           
        }
        
        return largestP;
    }

}

结束代码:

17 的完美幂是 1 TimeExec:获得 17 的完美幂:0.001s

625 的完美幂是 2 TimeExec:获得 625 的完美功率:0.026s

1024 的完美幂是 2 TimeExec:获得 1024 的完美幂:0.052s

10000 的完美幂是 2 TimeExec:获得 10000 的完美幂:1.9s

需要此代码在 .01s 下打印 1073741824 的完美幂是 X TimeExec:获得完美的力量:XX.XXXs

【问题讨论】:

  • 您的计算机需要 2+ 秒才能完成 10000?
  • 很像 1.9-2.0 秒,所以是的。我修复了帖子,因此它显示了输出代码。
  • 这与我要使用的代码不匹配,但无论如何谢谢。
  • 只需在 getPerfectPower 中添加一个 if 语句来检查 Math.pow(b,p) &gt; x 是否存在,如果是,则中断内部循环。将显着提高您的运行时间。如果这还不够,请注意b 需要一直运行到sqrt(x),然后您可以确定输出为 1。

标签: java algorithm performance timing


【解决方案1】:

首先,我们正在寻找参数中给出的完美幂数的最大指数。最大 exponent 的最佳候选者是 base 为 2,因此我们将从 2 而不是 1 开始循环。

其次,最小的exponent是2(除了fallback 1),所以最大base where base2 = xmaxBase = sqrt(x),所以我们将在那个 base 值处结束循环。

我们的目标是公式bp = x,我们有来自参数的x和来自循环的b,所以我们可以计算@987654323 @ 使用 p = log(x) / log(b),然后检查是否为整数。

避免舍入错误的最佳方法是舍入到最接近的整数,然后检查 bp == x

代码如下:

public static int getPerfectPower(int x) {
    double maxBase = Math.sqrt(x);
    for (int b = 2; b <= maxBase; b++) {
        long p = Math.round(Math.log(x) / Math.log(b));
        if (Math.pow(b, p) == x)
            return (int) p;
    }
    return 1;
}

测试

public static void main(String[] args) {
    test(17);
    test(625);
    test(1024);
    test(10000);
    test(1073741824);
}
static void test(int x) {
    long start = System.nanoTime();
    int exponent = getPerfectPower(x);
    long end = System.nanoTime();
    System.out.printf("Perfect Power of %d is %d (%.9fs)%n",
                      x, exponent, (end - start) / 1e9);
}

输出

Perfect Power of 17 is 1 (0.000022500s)
Perfect Power of 625 is 4 (0.000003700s)
Perfect Power of 1024 is 10 (0.000003700s)
Perfect Power of 10000 is 4 (0.000003500s)
Perfect Power of 1073741824 is 30 (0.000001700s)

或者,我们可以循环 exponent 而不是 base,将时间复杂度从 O(sqrt(x)) 更改为 O(log(x)),这在技术上更快,但这里的值太小,无法注意到任何性能差异。

不解释,代码如下:

public static int getPerfectPower(int x) {
    // x = b ^ p   <==>   p = log(x) / log(b)   <==>   b = exp(log(x) / p)
    double logX = Math.log(x);
    int maxExp = (int) Math.round(logX / Math.log(2));
    for (int p = maxExp; p > 1; p--) {
        long b = Math.round(Math.exp(logX / p));
        if (Math.pow(b, p) == x)
            return p;
    }
    return 1;
}

【讨论】:

    【解决方案2】:

    您正在使用从 1 到 x 的两个嵌套循环测试太多案例。

    对于指数p,您可以将最可能的基数计算为b0=floor(pow(x,1.0/p))。如果您想谨慎,请测试b=b0-1, b0, b0+1 的幂是否等于x,但b=b0-1 的情况永远不会有效。

    当达到b0=1 时,您可以停止增加指数。

    【讨论】:

      猜你喜欢
      • 2021-06-21
      • 1970-01-01
      • 2012-12-10
      • 1970-01-01
      • 1970-01-01
      • 2010-10-31
      • 1970-01-01
      • 2020-07-22
      • 1970-01-01
      相关资源
      最近更新 更多