Week14 Perfect Squares
Week14
Dynamic Programming
question source: 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.
question description
Example 1 :
Input: n = 12
Output: 3
Explanation: 12 = 4 + 4 + 4.
Example 2:
Input
Output: 2
Explanation: 13 = 4 + 9
解決方法
題目是說判斷一個數能最少用多少個平方數之和表示出來。這道題的標籤是DP問題。本來想是否能用貪心演算法表示出來,先將這個數分割成最大的平方數和另一個數,然後在另一個數中重複這個做法。但是很快就能看出一個反例。12 = 9 + 1 + 1 + 1需要4個,而最少其實是12 = 4 +4+4。然後就想用動態規劃來解決了。
先定義子問題,num[i]定義為i這個數能最小多少個平方數之各和來表示。則問題的解為num[n]。
然後定義開始值。要多一個額外的量num[0]為0, nums[1]為1。
class Solution {
public:
int numSquares(int n) {
int num[n + 1];
num[0] = 0;
num[1] = 1;
for(int i = 2; i <= n; i++){
int min = i;
for(int j = 2; j * j <= i; j++){
if(min > num[i - j * j] + 1){
min = num[i - j * j] + 1;
}
}
num[i] = min;
}
return num[n];
}
};
演算法複雜度是
這題的另一個標籤為Math,所以是可以通過數學方法來解決了。有一個定理叫四平方和定理,每一個正整數均可表示4個整數的平方和。還有一個Legendre’s three-square theorem,是說一個自然數能被表示為三個平方之和當且僅當它不符合 ,a和b是整數。因此可以用這些數學定理來解決。首先判斷這個數是否是某個數的平方,如果是,則返回1。其次,再判斷能否分為2個數之和,如果是,則返回2,再判斷是否是否符合前面的表示式,如果是,則返回4,否則返回3。
class Solution {
public:
bool isSquare(int n){
int sqr = floor(sqrt(n));
return sqr * sqr == n;
}
int numSquares(int n) {
if(isSquare(n)){
return 1;
}
for(int i = 1; i * i < n; i++){
if(isSquare(n - i * i)){
return 2;
}
}
int a = 1;
while(n % (4 * a) == 0){
a *= 4;
}
if((n / a) % 8 == 7){
return 4;
}
return 3;
}
};
是真的快,數學真的厲害啊!果然很多搞計算機的人才數學都不差。這個演算法複雜度是