279. Perfect Squares
Given a positive integer n, find the least number of perfect square numbers (for example,1, 4, 9, 16, ...
) which sum to n.
Example 1:
Input:
n = 12
Output: 3
Explanation:
12 = 4 + 4 + 4.
Example 2:
Input:
n = 13
Output: 2
Explanation:
13 = 4 + 9.
Thoughts:
- Dynamic Programming
- sq[i] = ... to number i
- sq[0] = 0
- search from 1 to j (j ^2 <= i): sq[i] = min(sq[i], sq[i-j^2] + 1)
- Static Dynamic Programming
- sq[i]: ... to number i
- sq[0] = 0
- in the loop, each time push the result for sq[i] into ith of the container.
- Mathematical Solution
- Lagrange's Four Square Theorem: Any natural number can be represented by the sum of at most 4 perfect square numbers
- number that need 4 perfect square meets: 4^k(8m + 7)
- BFS
- Each node a number
- An edge between i and j exists if from node i to j, there is only one perfect number away.
Code 1:
class Solution {
public:
int numSquares(int n) {
vector<int> sq (n + 1, INT_MAX);
sq[0] = 0;
for(int i = 1; i < n + 1; i++){
for(int j = 1; j * j <= i ; j++){
sq[i] = min(sq[i], sq[i - j*j] + 1);
}
}
return sq[n];
}
};
Code 2:
class Solution {
public:
int numSquares(int n) {
if( n <= 0 ) return 0;
static vector<int> sq ({0});
while(sq.size() <= n){
int m = sq.size();
int cur = INT_MAX;
for(int i = 1; i * i <= m; i++){
cur = min(cur, sq[m - i * i] + 1);
}
sq.push_back(cur);
}
return sq[n];
}
};
Code 3: Lagrange's Four Square Theorem
class Solution {
private:
int is_square (int n){
int sqrt_n = (int) (sqrt(n));
return ( sqrt_n * sqrt_n == n);
}
public:
int numSquares(int n) {
// result of 1:
if(is_square(n)) return 1;
// Based on Lagrange's Four Square theorem, there
// are only 4 possible results: 1, 2, 3, 4.
// result of 4: 4^k(8m + 7) https://en.wikipedia.org/wiki/Lagrange%27s_four-square_theorem
while((n & 3) == 0) n >>= 2; // n%4 == 0
if((n & 7) == 7) return 4; // n%8 == 7
// result of 2:
int sqrt_n = (int)(sqrt(n));
for(int i = 1; i <= sqrt_n; i++){
if(is_square(n - i * i)) return 2;
}
return 3;
}
};
Code 4: BFS: O(n*E)
class Solution {
public:
int numSquares(int n) {
if(n <= 0){
return 0;
}
vector<int> perfectSquares;
vector<int> record (n);
for(int i = 1; i * i <= n; i++){
perfectSquares.push_back(i * i);
record[i * i - 1] = 1;
}
if(perfectSquares.back() == n) return 1;
queue<int> q;
for(auto& num: perfectSquares){
q.push(num);
}
int count = 1;
while(!q.empty()){
count++;
int size = q.size();
for(int i = 0; i < size; i++){
int curNum = q.front();
for(auto& sqNum: perfectSquares){
if(curNum + sqNum == n) return count;
else if((curNum + sqNum < n) && (record[curNum + sqNum - 1] == 0)){
q.push(curNum + sqNum);
record[curNum + sqNum - 1] = 1; //add into the queue, mark as explored
}
else if( curNum + sqNum > n) break;
}
q.pop();
}
}
return 0;
}
};