完美平方算法 - 实现解释

Posted

技术标签:

【中文标题】完美平方算法 - 实现解释【英文标题】:perfect square algorithm - explanation for the implementation 【发布时间】:2014-03-26 16:23:20 【问题描述】:

这个问题是对这里帖子的后续跟进:Fastest way to determine if an integer's square root is an integer、What's a good algorithm to determine if an input is a perfect square?。

那里的一个帖子有这个解决方案来查找给定数字是否为perfect square

public final static boolean isPerfectSquare(long n)
    
        if (n < 0)
            return false;

        switch((int)(n & 0xF))
        
        case 0: case 1: case 4: case 9:
            long tst = (long)Math.sqrt(n);
            return tst*tst == n;

        default:
            return false;
        
     

这是一个简洁的解决方案,并且运行良好。但是没有解释它是如何工作的,或者更重要的是,没有详细解释这个解决方案是如何得出的。 我想知道这个解决方案是如何得出的。

【问题讨论】:

如果一个数是一个完全平方,它的平方根是一个整数。所以你只取平方根。由于浮动算术不准确,因此您不要尝试检查平方根是否为整数,只需将其四舍五入到最接近的整数并检查该整数是否是您的数字的平方根。 这似乎利用了这样一个事实:一个完美的正方形除以 16 只能有 0、1、4 或 9 作为余数。数学网站可能更有资格解释为什么会这样。 @Kevin,在这种情况下,用尽证明(列举所有 15 个案例)就足够了。请注意,平方的最低有效位仅受其根的最低有效位影响。 【参考方案1】:

n &amp; 0xF 只选择 n 的最后 4 位,因为 0xF 在二进制中是 1111。实际上相当于n除以16的余数。

该算法利用了这样一个事实:对于完美正方形,mm % 16 只能是 0149 之一。可以证明如下:

任何自然数n 都可以表示为4k4k+14k+24k+3(对于某些自然数k)。

那么,n^2 可以是 (4k)^2(4k+1)^2(4k+2)^2(4k+3)^2。 => n^2 可以是 16k^216k^2+8k+116k^2+16k+416k^2+24k+9

如果n^216k^2,那么n^2 % 16 显然是0。

如果n^216k^2+8k+1n^2 % 16 = (8k+1) % 16 = (8k % 16) + 1 = 0 or 9,取决于k 是偶数还是奇数。

如果n^216k^2+16k+4,则n^2 % 16 = 4

如果n^216k^2+24k+9n^2 % 16 = (24k+9) % 16 = (16k+8k+9) % 16 = 1 or 9 取决于 k 是奇数还是偶数。

因此,n^2 % 16 只能是0,1, 4 or 9

【讨论】:

你忘了显示 16k^2+16k+4 % 16 = 4。所以你的答案应该是因此,n^2 % 16 只能是 0,1 4 或 9。【参考方案2】:

虽然这个问题不是直接与编程有关,但它仍然与选择的解决方法有关。这就是为什么我会发布正确的解释。显然,x &amp; 0xF 仅相当于 x % 16 - 即从除法到 16 的模(因为 is 会留下相应的位。但是,这个技巧只适用于 2 的幂)。

这个方法是基于关于完美正方形的非常重要的事情:

如果整数 K 除以任何整数 b 并以 r 为模(所以 K%b = r)然后 K2 和 r 2 除以b 将得到相同的模数。

为什么?事实上,我们有: K2-r2 = (Kr)(K+r) 并且K-r 将被除以b 并得到整数结果(因为@ 987654331@ 是 K 的模除以 b)

这就是b=16的原因:

r r^2 (r^2)%16 0 ----> 0 ---> 0 1 ----> 1 ---> 1 2 ----> 4 ---> 4 3 ----> 9 ---> 9 4 ---> 16 ---> 0 5 ---> 25 ---> 9 6 ---> 36 ---> 4 7 ---> 49 ---> 1 8 ---> 64 ---> 0 9 ---> 81 ---> 1 10 --> 100 ---> 4 11 --> 121 ---> 9 12 --> 144 ---> 0 13 --> 169 ---> 9 14 --> 196 ---> 4 15 --> 225 ---> 1

所以,如您所见,如果r 是从完美平方除法导出的,那么模必须r^2%16 的模相同 - 因此,它只能 0149

更重要的一点:这是完美平方的必要条件,而不是足够条件(所以重点是 “如果模不是 0,1,4或 9,则数字不是完美平方”,但仍不等于 “如果模数为 0、1、4 或 9,则数字为完美平方” 简单示例为 @987654341 @: 17%16 = 1 但是 17 不是完美的平方)这就是为什么即使满足模条件,方法仍然使用

返回 tst*tst == n;

-即通过计算它的平方根来测试n 是完美的平方。所以这个方法大约会快 4 倍 - 因为从 16 个可能的模 r 到 12 我们总是可以返回 false

【讨论】:

这让我隐约想起了质数的轮因式分解。这是消除非主要候选人的快速方法。 en.wikipedia.org/wiki/Wheel_factorization. 它可以用于那个,是的(事实上它是)。实际上,带有因式分解的案例也依赖于必要条件(显然还不够)

以上是关于完美平方算法 - 实现解释的主要内容,如果未能解决你的问题,请参考以下文章

有人可以向我解释为啥完美平方是 O(sqrt(n)) 的运行时间吗?

513. 完美平方

513. 完美平方

算法#03--具体解释最小二乘法原理和代码

计算乘法为完美平方的所有可能对的有效算法[关闭]

再论力扣第279题--完全平方数