LeetCode(力扣) :完全平方数

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/perfect-squares

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

示例 1:

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

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

动态规划,背包解法
参考: https://leetcode-cn.com/problems/perfect-squares/solution/hua-jie-suan-fa-279-wan-quan-ping-fang-shu-by-guan/

每个数都可以看做一个数和一个平方数的和,即 num = s + a^2,同理 s 也可以看做一个数和另一个平方数的和, 最糟糕的情况就是好多个1 相加等于自身
这里用一个数组将小于等于num 的每个数所需要的最少需要的平方数的个数记录下来,即每个数对应的最优解

class Solution {
    public int numSquares(int n) {
        int[] dp = new int[n + 1]; // 默认初始化值都为0
        for (int i = 1; i <= n; i++) {
            dp[i] = i; // 最坏的情况就是每次+1
            for (int j = 1; i - j * j >= 0; j++) { 
                dp[i] = Math.min(dp[i], dp[i - j * j] + 1); // 动态转移方程
            }
        }
        return dp[n];
    }
}

背包问题理解过程:
https://www.cnblogs.com/toone/p/8554817.html

还有一种方法
理论是:
拉格朗日四平方和定理
四平方和定理:每个正整数均可表示成4个整数的平方和。

注意有些整数不可表示为3个整数的平方和,例如7。

等价的说法是:每个正整数均可表示成不超过四个整数的平方之和。

重要推论:

  1. 数 n 只能表示成四个整数的平方和,不能表示成更少个数的平方和,必定满足 4a(8b+7).

  2. 如果 n%4==0,k=n/4,n 和 k 可由相同个数的整数表示

如何利用推论求一个正整数最少需要多少个数的平方和表示:

  1. 先判断这个数是否满足 4a(8b+7),如果满足,那么这个数就至少需要 4 个数的平方和表示。

  2. 如果不满足,再在上面除以 4 之后的结果上暴力尝试只需要 1 个数就能表示和只需要 2 个数就能表示的情况。

  3. 如果还不满足,那么就只需要 3 个数就能表示。

具体数学定理连接: https://www.cnblogs.com/lfri/p/11717745.html

代码:
链接:https://leetcode-cn.com/problems/perfect-squares/solution/python-3xing-dp-bfs-xiang-jie-by-knifezhu/

class Solution:
    def numSquares(self, n: int) -> int:
        while n % 4 == 0:
            n /= 4
        if n % 8 == 7:
            return 4
        
        a = 0
        while a**2 <= n:
            b = int((n - a**2)**0.5)
            if a**2 + b**2 == n:
                return bool(a) + bool(b)
            a += 1
        
        return 3

猜你喜欢

转载自blog.csdn.net/zZsSzss/article/details/103387942