1. 程式人生 > 其它 >leetcode279. 完全平方數(動態規劃 完全揹包 數學方法)

leetcode279. 完全平方數(動態規劃 完全揹包 數學方法)

連結:https://leetcode-cn.com/problems/perfect-squares/

題目

給定正整數n,找到若干個完全平方數(比如1, 4, 9, 16, ...)使得它們的和等於 n。你需要讓組成和的完全平方數的個數最少。

給你一個整數 n ,返回和為 n 的完全平方數的 最少數量 。

完全平方數 是一個整數,其值等於另一個整數的平方;換句話說,其值等於一個整數自乘的積。例如,1、4、9 和 16 都是完全平方數,而 3 和 11 不是。

用例

示例1:

輸入:n = 12
輸出:3
解釋:12 = 4 + 4 + 4
示例 2:

輸入:n = 13
輸出:2
解釋:13 = 4 + 9

提示:

1 <= n <= 104

思路

方法1
完全揹包
題目可以理解為將 1,4,9···等完全平方數作為物品放入 容量為n的揹包中 其中每個物品都可以用無限次 求塞滿揹包時物品數量最少的情況
我做的時候先遍歷物品再遍歷容量
由於物品中有1的存在 ,所以任意大小揹包必能被填滿(全用1)
設定大小為n+1的dp陣列,初始化dp[i]=i
轉移方程即為 dp[j]=min(dp[j],dp[j-ii]+1) j>=ii

class Solution {
public:
    int numSquares(int n) {
        int s=sqrt(n);
        vector<int>dp(n+1);
        for(int i=0;i<n+1;++i)
        {
            dp[i]=i;
        }

        for(int i=2;i*i<=n;++i)
        {
            int p=i*i;
            for(int j=1;j<n+1;++j)
            {
                if(j>=p)
                {
                    dp[j]=min(dp[j-p]+1,dp[j]);
                }
            }
        }
        return dp[n];
    }
};

實際上也可以先遍歷容量再遍歷物品 取每個容量下啊的最小值

class Solution {
public:
    int numSquares(int n) {
        vector<int> f(n + 1);
        for (int i = 1; i <= n; i++) {
            int minn = INT_MAX;
            for (int j = 1; j * j <= i; j++) {
                minn = min(minn, f[i - j * j]);
            }
            f[i] = minn + 1;
        }
        return f[n];
    }
};

數學方法
四平方和問題 n = (4^a)*(8b+7)

  1. 任何正整數都可以拆分成不超過4個數的平方和 ---> 答案只可能是1,2,3,4
  2. 如果一個數最少可以拆成4個數的平方和,則這個數還滿足 n = (4^a)*(8b+7) ---> 因此可以先看這個數是否滿足上述公式,如果不滿足,答案就是1,2,3了
  3. 如果這個數本來就是某個數的平方,那麼答案就是1,否則答案就只剩2,3了
  4. 如果答案是2,即n=a2+b2,那麼我們可以列舉a,來驗證,如果驗證通過則答案是2
  5. 只能是3
class Solution {
public:
    int numSquares(int n) {
        int x=n,y=sqrt(n);
        if(y*y==n)
            return 1;
        while(x%4==0)
            x/=4;
        if(x%8==7)
            return 4;
        for(int i=1;i<=y;++i)//判斷是2還是3 判斷n減去一個平方數後是否還是平方數
        {
            int j=n-i*i;
            int p=sqrt(j);
            if(p*p==j)
                return 2;
        }
        return 3;
    }
};