279.完全平方數
阿新 • • 發佈:2021-10-02
目錄
279.完全平方數
題目
給定正整數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 來源:力扣(LeetCode) 連結:https://leetcode-cn.com/problems/perfect-squares 著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。 ## 題解 給定正整數n,找到若干個完全平方數(比如1, 4, 9, 16, ...)使得它們的和等於 n。 ---> 從一個數組(一堆數)中按一定的選取方式得到目標target,嘗試將題目進行轉化為揹包問題。 揹包的容量是n,物品是從 1*1、2*2、3*3...、m*m中選擇,其中m*m<=,每個物品可以多次選擇,那麼這是一道完全揹包問題。 **1.確定dp[j]及下標的含義** dp[j]:表示組成j的完全平方數個數最少為dp[j]。 **2.遞推公式** dp[j]可以由兩種方式推出。 假設當前物品是num - 組成j-num的完全平方數個數最少為dp[j-num],那麼此時num放入之後,組成j的完全平方數個數為dp[j-num]+1。 - 當前num不放入,之前的物品已經組成了j的揹包,個數為dp[j] 題目要求求最少的個數,那麼遞推式為`dp[j]=Math.min(dp[j],dp[j-num]+1)` **3.dp陣列如何初始化** n=0,dp[0]=0 n≠0,涉及到求最小值,那麼初始化應該為Integer.MAX_VALUE **4.確定遍歷順序** 這是求最少的個數,不涉及什麼組合排序,所以都可以。 先從小到大遍歷物品,再從小到大遍歷揹包。 ```java for(int i=1;i*i<=n;i++){ int num = i*i; for(int j=num;j<=n;j++){ //if(dp[j-num]!=Integer.MAX_VALUE) 這個註釋掉是因為總會由辦法湊齊1+1+1+... dp[j]=Math.min(dp[j],dp[j-num]+1); } }
5.舉例推導dp陣列
n=4
程式碼
class Solution { public int numSquares(int n) { int [] dp = new int [n+1]; Arrays.fill(dp,Integer.MAX_VALUE); dp[0] = 0; for(int i=1;i*i<=n;i++){ int num=i*i; for(int j=num;j<=n;j++){ dp[j]=Math.min(dp[j],dp[j-num]+1); } } return dp[n]; } }