题目 - LeetCode 279:完全平方数(Perfect Squares)
给你一个整数 n ,返回 和为 n 的完全平方数的最少数量 。
完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。
详解
我们可以使用 动态规划(DP) 来解决这个问题。
什么是完全平方数?
完全平方数是形如 1, 4, 9, 16, 25...
的数,即某个整数的平方。
✅ 状态定义
设 dp[i]
表示“和为 i
的最少完全平方数的数量”。
🔁 状态转移方程
dp[i] = min(dp[i - j*j] + 1) // 对于所有 j*j <= i
❓ 为什么这样写?
我们试图把 i
拆成一个较小的数 i - j*j
加上一个平方数 j*j
。
如果我们已经知道 dp[i - j*j]
,那么 dp[i]
最多只需要 dp[i - j*j] + 1
个数字。
我们尝试所有可能的平方数 j*j ≤ i
,找出最小的组合。
💻 Swift 实现代码
func numSquares(_ n: Int) -> Int {
var dp = [Int](repeating: Int.max, count: n + 1)
dp[0] = 0
for i in 1...n {
var j = 1
while j * j <= i {
dp[i] = min(dp[i], dp[i - j * j] + 1)
j += 1
}
}
return dp[n]
}
🧮 示例
numSquares(12) // 输出 3 => 4 + 4 + 4
numSquares(13) // 输出 2 => 4 + 9
📊 时间复杂度分析
- 外层循环执行
n
次 - 内层循环最多执行
√n
次
总复杂度:O(n√n)
空间复杂度:O(n)