279. Perfect Squares
MediumDescription
給定正整數
n,找出最少需要多少個完全平方數(1, 4, 9, 16, …)的和等於n。
Example:
Input: n = 12 Output: 3
Intuition#
完全背包變體:物品是所有完全平方數,求湊成 n 的最少物品數。
dp[i]= 組成i所需的最少完全平方數個數- 對每個
i,嘗試所有j*j <= i的完全平方數 - 狀態轉移:
dp[i] = min(dp[i - j*j] + 1)for all validj
Approaches#
1: Top-Down Memoization#
- 概念: 遞迴嘗試減去每個完全平方數,記憶化結果
- 時間複雜度:
O(n * sqrt(n)) - 空間複雜度:
O(n)
class Solution {
fun numSquares(n: Int): Int {
val memo = IntArray(n + 1) { -1 }
fun dp(rem: Int): Int {
if (rem == 0) return 0
if (memo[rem] != -1) return memo[rem]
var best = rem // 最差情況全用 1
var j = 1
while (j * j <= rem) {
best = minOf(best, dp(rem - j * j) + 1)
j++
}
memo[rem] = best
return best
}
return dp(n)
}
}⭐2: Bottom-Up DP#
- 概念: 從 1 到 n 逐步計算每個值的最少完全平方數個數
- 時間複雜度:
O(n * sqrt(n)) - 空間複雜度:
O(n)
class Solution {
fun numSquares(n: Int): Int {
val dp = IntArray(n + 1) { it } // 最差全用 1
for (i in 1..n) {
var j = 1
while (j * j <= i) {
dp[i] = minOf(dp[i], dp[i - j * j] + 1)
j++
}
}
return dp[n]
}
}🔑 Takeaways#
- Pattern: 完全背包 — 物品為完全平方數,容量為 n,求最少物品數
- 關鍵技巧: 初始化
dp[i] = i(全用 1 來湊),保證有一個合法上界;根據 Lagrange 四平方和定理,答案最多為 4