279.Perfect Squares === ###### tags: `Medium`,`DP`,`Math` [279. Perfect Squares](https://leetcode.com/problems/perfect-squares/) ### 題目描述 Given an integer `n`, return *the least number of perfect square numbers that sum* to `n`. A **perfect square** is an integer that is the square of an integer; in other words, it is the product of some integer with itself. For example, `1`, `4`, `9`, and `16` are perfect squares while `3` and `11` are not. ### 範例 ``` Input: n = 12 Output: 3 Explanation: 12 = 4 + 4 + 4. ``` ``` Input: n = 13 Output: 2 Explanation: 13 = 4 + 9. ``` ### 解答 #### Javascript 解法一 根據四平方和定理,每一個正整數均可以表示為4個整數的平方和。 ```javascript= function numSquares(n) { const squares = []; for (let i = 1; i <= n; i++) { if (Math.sqrt(i) % 1 === 0) { if (i === n) return 1; for (let j = 0; j < 4; j++) { squares.push(i); } } } // Two Sum let right = squares.length - 1; for (let i = 0; i < squares.length; i++) { const sum = squares[i] + squares[right]; if (sum === n) return 2; if (sum > n) { right--; } } // Three Sum for (let i = 0; i < squares.length - 2; i++) { let left = i + 1; let right = squares.length - 1; while (left < right) { const sum = squares[i] + squares[right] + squares[left]; if (sum === n) return 3; if (sum > n) { right--; } else { left++; } } } return 4; // 4sum沒必要 } ``` > [name=Marsgoat] [time= Nov 22, 2022] 解法二 跟大家學的DP ```javascript= function numSquares3(n) { const dp = new Array(n + 1).fill(Infinity); dp[0] = 0; for (let i = 1; i <= n; i++) { for (let j = 1; j * j <= i; j++) { dp[i] = Math.min(dp[i], dp[i - j * j] + 1); } } return dp[n]; } ``` > [name=Marsgoat] [time= Nov 23, 2022] #### Python 很慢的DP ```python= class Solution(object): def numSquares(self, n): """ :type n: int :rtype: int """ # init dp = [0] + [float("inf") for _ in range(n)] num = 1 square_num = 1 while (square_num <= n): # update dp array from square num for idx in range(square_num, n+1): dp[idx] = min(dp[idx], dp[idx - square_num] + 1) num += 1 square_num = num* num return dp[n] ``` > [name=DT] [time= Nov 22, 2022] 依舊很慢的 DP ```python= class Solution: def numSquares(self, n: int) -> int: table = [i for i in range(1, n+1)] good_point = [] for i in range(1, n+1): if int(i**0.5) == i**0.5: table[i-1] = 1 good_point.append(i) else: for j in good_point: if table[j-1] == 1: v = table[j-1] + table[i-j-1] if v < table[i-1]: table[i-1] = v return table[n-1] ``` > [name=gpwork4u] [time= Nov 22, 2022] #### C++ 也很慢的DP ```cpp= 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[n]; } ``` > [name=XD] [time= Nov 22, 2022] ### Reference [Lagrange's four-square theorem](https://en.wikipedia.org/wiki/Lagrange%27s_four-square_theorem) [回到題目列表](https://hackmd.io/@Marsgoat/leetcode_every_day)