题目
给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
示例 1:
输入: n = 12
输出: 3
解释: 12 = 4 + 4 + 4.
示例 2:
输入: n = 13
输出: 2
解释: 13 = 4 + 9.
方案一(BFS)

**
import functoolsimport collectionsclass Solution:def numSquares(self, n: int) -> int:deque = collections.deque([n])res = 0while deque:length = len(deque)res += 1for _ in range(length):num = deque.popleft()for square_num in self.getSquareNumList(num):t = num - square_numif t == 0:return resdeque.append(t)return -1@functools.lru_cache(maxsize=None)def getSquareNumList(self, n: int):'''获取小于等于n的完全平方数列表'''square_nums = []i = 1while i * i <= n:square_nums.append(i * i)i += 1return square_nums
方案二(数学定理)
Lagrange 四平方定理: 任何一个正整数都可以表示成不超过四个整数的平方之和。
满足四数平方和定理的数n(这里要满足由四个数构成,小于四个不行),必定满足
class Solution:def numSquares(self, n: int) -> int:if n < 4:return n# 4^k * (8a + 7)while n % 4 == 0:n /= 4if n % 8 == 7:return 4a = 0while a ** 2 <= n:b = int((n - a ** 2) ** 0.5)if a ** 2 + b ** 2 == n:return bool(a) + bool(b)a += 1return 3
方案三(动态规划)
import functoolsclass Solution:def numSquares(self, n: int) -> int:# 递推公式# dp[i] = min(dp[i], dp[i − j] + 1)dp = [i for i in range(n + 1)] # 初始化dpfor i in range(2, n + 1):for j in self.getSquareNumList(i):dp[i] = min(dp[i], dp[i - j] + 1)return dp[-1]@functools.lru_cache(maxsize=None)def getSquareNumList(self, n: int):'''获取小于等于n的完全平方数列表'''square_nums = []i = 1while i * i <= n:square_nums.append(i * i)i += 1return square_nums
原文
https://leetcode-cn.com/explore/learn/card/queue-stack/217/queue-and-bfs/874/
https://leetcode-cn.com/problems/perfect-squares/solution/dong-tai-gui-hua-bfs-zhu-xing-jie-shi-python3-by-2/
