[LeetCode] 279. Perfect Squares 完全平方数

[LeetCode] 279. Perfect Squares 完全平方数

问题描述:给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, …)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。

示例 1:

输入: n = 12
输出: 3 
解释: 12 = 4 + 4 + 4.

示例 2:

输入: n = 13
输出: 2
解释: 13 = 4 + 9.

1. 数学定理

完全平方指用一个整数乘以自己例如1 * 1,2 * 2,3 * 3等,依此类推。若一个数能表示成某个整数的平方的形式,则称这个数为完全平方数
四平方和定理:每个正整数均可表示为不超过4个完全平方数的和。 因为任何数加上0²都不变。所以对于不够4个完全平方数的可以用0²补齐,于是四平方和定理等价为:任意一个正整数都可以写成4个完全平方数的和。 它是费马多边形数定理华林问题的特例。
注意有些整数不可表示为3个完全平方数的和,例如7。

1743年,瑞士数学家欧拉发现了一个著名的恒等式:

(a2 + b2 + c2+ d2)(x2 + y2 + z2+ w2) = (ax + by + cz + dw)2 + (ay - bx + cw - dz)2 + (az - bw - cx + dy)2 + (aw + bz - cy - dx)2

根据上述欧拉恒等式或四元数的概念可知如果正整数m和n能表示为4个整数的平方和,则其乘积mn也能表示为4个整数的平方和。于是为证明原命题只需证明每个素数可以表示成4个整数的平方和即可。

1751年,欧拉又得到了另一个一般的结果。

对任意奇素数 p,同余方程 x2+y2+1≡0(mod p)必有一组整数解x,y满足0≤x<p/2,0≤y<p/2 (引理一)

同余方程是一个数学方程式。该方程式的内容为:对于一组整数Z,Z里的每一个数都除以同一个数m,得到的余数可以为0,1,2,…m-1,共m种。我们就以余数的大小作为标准将Z分为m类。每一类都有相同的余数。

至此,证明四平方和定理所需的全部引理已经全部证明完毕。此后,拉格朗日和欧拉分别在1770年和1773年作出最后的证明。

扫描二维码关注公众号,回复: 3351972 查看本文章

2. 代码实现

2.1 根据四平方和定理

根据四平方和定理,结果就是1,2,3,4中的一个。首先需要对数字进行简化,有两条规则:
规则1:如果这个数对4取余得0,可以把4除去(易知,这个过程可以不断重复),不影响结果;
规则2:对4取余结束后,如果这个数对8取余得7,则这个数是四个完全平方数的和;
根据规则1,先对这个数不断除4(满足除的条件的话)。然后根据规则2,如果这个数对8取余得7,则结果是4,否则,结果是1,2,3中的一个。显然,1,2很容易验证,若都不是那么就一定是3了。所以,过程变得简洁了很多。代码如下:

class Solution {
public:
    int numSquares(int n) {
        while(n % 4 == 0) { 
            n /= 4;
        }
        if(n % 8 == 7) { 
            return 4;
        }
        for(int a = 0; a * a <= n; ++a) {
            int b = sqrt(n - a * a);
            if(a * a + b * b == n) { 
                return !!a + !!b; 
            }
        }
        return 3;
    }
};

上面 !!a+!!b 可以看成是把 int 型转换成 bool 型。

2.2 动态规划

0 开始到 n 计算每一个整数 i 的最少完全平方数个数 dp[i] ,得到 dp[i] 后,计算 dp[i+j*j] ,只要 i+j*j<=n 就可以一直计算下去,最后返回 vector 的最后一个元素。代码如下:

class Solution {
public:
    int numSquares(int n) {
        vector<int> dp(n + 1, INT_MAX);
        dp[0] = 0;
        for(int i = 0; i <= n; ++i){
            for(int j = 1; i + j * j <= n; ++j){
                dp[i + j * j] = min(dp[i + j * j], dp[i] + 1);
            }
        }
        return dp.back();
    }
};

参考资料
https://baike.baidu.com/item/完全平方数/8025061?fr=aladdin
https://baike.baidu.com/item/四平方和定理/4507832?fr=aladdin
https://www.cnblogs.com/grandyang/p/4800552.html.

猜你喜欢

转载自blog.csdn.net/qq_35481167/article/details/82817699