【问题标题】:Get powers of a perfect power number获得完美幂数的幂
【发布时间】:2020-07-26 07:45:34
【问题描述】:

我有一个问题是找到任何数字的 2 次幂(没有任何幂的数字,例如 5 将返回 null),幂是和 2 个整数,当添加幂以返回所述数字时。以下是一些示例:

4 -> {2, 2}
5 -> null 
6 -> null
7 -> null
8 -> {2, 3}
10 -> null
etc...

虽然我下面的代码可以工作,但是它太慢了,当通过问题时(大约 100 个 integer.max 值)它会占用设定的时间(16 秒),我可以优化这段代码吗?

public static int[] isPerfectPower(int n) {  
    int limit = (int)Math.round((n/((double)5/2)));

    for (int i = 2; i <= limit; i++) {  
        double result = Math.pow(n, (double)1/i);   
        result = (double)Math.round(result * Math.pow(10, 10)) /  Math.pow(10, 10);
        if((result == Math.floor(result))) return new int[] {(int)result, i};
    }
    return null;
}

【问题讨论】:

  • @backdoor 感谢您的回复,但可以详细说明这如何加快我的代码速度?
  • 您的代码很好,但您的limit 太大了。鉴于pow(2, 31) = 2147483648 超出了Java int 的范围,您的幂指数不可能大于30,因此您永远不需要大于30limit。对于较小的n,您可以使用较小的限制,但从简单的角度来看,简单地为所有n 硬编码30 的限制就足够了。 (如果你想变得花哨,你也可以测试 2 的幂,那么你需要考虑的最大指数是19,因为pow(3, 20) 对于 Java int 来说又太大了。)
  • @MarkDickinson:您应该将其发布为答案!

标签: java algorithm performance math


【解决方案1】:

您的输入不超过 2147483647,这意味着只有这么多可能的答案。这是所有 108 个完美幂的有序列表,幂为 5 或更高。

2**5, 2**7, 3**5, 4**5, 2**11, 3**7, 5**5, 6**5, 2**13, 4**7, 7**5, 8**5, 9**5, 5**7, 10**5, 2**17, 11**5, 3**11, 12**5, 6**7, 13**5, 2**19, 14**5, 15**5, 7**7, 16**5, 17**5, 3**13, 18**5, 8**7, 19**5, 20**5, 21**5, 4**11, 9**7, 22**5, 23**5, 24**5, 2**23, 25**5, 10**7, 26**5, 27**5, 28**5, 11**7, 29**5, 30**5, 31**5, 32**5, 12**7, 33**5, 34**5, 5**11, 35**5, 36**5, 13**7, 4**13, 37**5, 38**5, 39**5, 40**5, 14**7, 41**5, 3**17, 42**5, 43**5, 44**5, 15**7, 45**5, 46**5, 47**5, 48**5, 16**7, 49**5, 50**5, 51**5, 6**11, 52**5, 17**7, 53**5, 54**5, 55**5, 2**29, 56**5, 57**5, 18**7, 58**5, 59**5, 60**5, 61**5, 19**7, 62**5, 63**5, 64**5, 65**5, 3**19, 5**13, 66**5, 20**7, 67**5, 68**5, 69**5, 70**5, 21**7, 71**5, 72**5, 7**11, 73**5

因此,您只需检查上面列表的正方形、立方体和主菜。

更简单的方法是检查所有十个幂 2、3、5、7、11、13、17、19、23 和 29。您不需要检查任何其他幂,因为它们也是非素数或太大而无法工作。

【讨论】:

    【解决方案2】:

    正如@Mark Dickinson 建议的那样,对我的代码最有效的更改(不完全更改它)是将我的限制限制在 30 而不是 n 的 2/3,因为任何大于 2 且功率大于 30 的数字都会超过了 Integer.max 的限制,因此添加一个额外的表达式 ( i

          public static int[] isPerfectPower(int n) {
            for(int i = 2; i <= ((n < 30) ? n : 30) && i < 30; i++) {
                double result = (double)Math.round(Math.pow(n, (double)1/i) * Math.pow(10, 10)) /  Math.pow(10, 10);
                if((result == Math.floor(result))) return new int[] {(int)result, i};
            }
            return null;
          }
    

    【讨论】:

    • 所有更改均由@Mark Dickinson 提供,谢谢!
    【解决方案3】:

    你可以通过分解一个数字来做到这一点。

    n = p1^k1 * p2^k2 * p3^k3 其中 p1,p2,p3 = 素数。

    如果gcd(k1, k2, k3) != 1(它们需要有公约数),那么一个数字将是完美的幂..

    例子:

    2500 = 2^2 * 5^4
         = 2^2 * (5^2)^2
         = 2^2 * 25^2
         = 50^2
    

    这样你可以计算完美幂的幂。

    方式 2:

    n = a^b ...你需要找到a &amp; b where b &lt; log(n)...

    现在你需要找到a.. 你可以使用二分搜索找到a。这种复杂性log(a)...计算a^b1.....你需要log(n)操作。

    所有二元运算的复杂度:(log(n) * log log(n))

    总复杂度:log(n) * (log(n) * log log(n))

    【讨论】:

    • 保理很慢。尝试所有可能的根源;它们只有 log2(n) 个。
    • 有很多方法可以做到这一点。如果 A
    • 其实我意识到你只需要检查素根;其中只有 O(log n / log log n);在这种情况下为 11 表示 32 位整数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-02-04
    • 1970-01-01
    • 2017-01-09
    • 2015-01-08
    • 1970-01-01
    • 1970-01-01
    • 2012-10-10
    相关资源
    最近更新 更多