1. 程式人生 > >Week14 Perfect Squares

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

: n = 13
Output: 2
Explanation: 13 = 4 + 9

解決方法

題目是說判斷一個數能最少用多少個平方數之和表示出來。這道題的標籤是DP問題。本來想是否能用貪心演算法表示出來,先將這個數分割成最大的平方數和另一個數,然後在另一個數中重複這個做法。但是很快就能看出一個反例。12 = 9 + 1 + 1 + 1需要4個,而最少其實是12 = 4 +4+4。然後就想用動態規劃來解決了。
先定義子問題,num[i]定義為i這個數能最小多少個平方數之各和來表示。則問題的解為num[n]。

n

u m [ i ] = m i n {
n u m [ i j j ] + 1 , i > = j j } num[i] = min \{num[i - j * j] + 1, i >= j * j\}
然後定義開始值。要多一個額外的量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];
    }
};

演算法複雜度是 O ( n l o g n ) O(nlogn)

這題的另一個標籤為Math,所以是可以通過數學方法來解決了。有一個定理叫四平方和定理,每一個正整數均可表示4個整數的平方和。還有一個Legendre’s three-square theorem,是說一個自然數能被表示為三個平方之和當且僅當它不符合 n = 4 a ( 8 b + 7 ) n = 4^a(8 * b + 7) ,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;
    }
};

是真的快,數學真的厲害啊!果然很多搞計算機的人才數學都不差。這個演算法複雜度是 O ( l o g n ) O(logn)