1. 程式人生 > >【LeetCode】279. Perfect Squares

【LeetCode】279. Perfect Squares

Description:

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.

 題目分析:

這是一道動態規劃題目,要解決動態規劃題目需要掌握三個資訊:

  • 最優子結構(最難的是發現最優子結構)
  • 邊界條件
  • 根據最優子結構寫出狀態轉移方程

重疊子問題:

我們用陣列dp[i]表示第i個數字的完美平方數。我們來尋找重疊子問題:

 我們要找到13的完美平方數,就把13拆成兩個數的和,在分別找到這兩個數的完美平方數,這就是這道題的重疊子問題。但是有一點我們不能忽略,如果這個13剛好是一個數的平方,那麼它的完美平方數就是1。

最優子結構分析:

13的完美平方數 = Min( dp[i]+dp[13-i] , dp[13]) ; i = 1到 13/2。

狀態轉移方程:

根據上面分析出來的最優子結構,我們可以寫出來這道題的狀態轉移方程:

dp[i] = Math.min(dp[j] + dp[i - j],dp[i])

 i 的完全平方數是從和為 i 的兩個完全平方數 dp[j] 和 dp[i-j]之和 與 dp[i ]中取最小。

【類似題目】

已經AC的程式碼:

import java.util.Arrays;

public class Numsquares_279 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		for(int i=1; i<=20; i++)
			System.out.println(numSquares(i));
	}
	
    public static int numSquares(int n) {
    	int[] dp = new int[n+1];
    	Arrays.fill(dp, Integer.MAX_VALUE);
    	dp[1] = 1;
    	for(int i=1; i<=n; i++) {
    		int sqr = (int)Math.sqrt(i);
    		//如果i本身是個平方數,就將dynamicProgramming[i]置為1
    		if(sqr * sqr == i)
    			dp[i] = 1;
    		else {
    			//從1開始遍歷所有和為i的最優解dp[i],使得dp[i]取值最小
    			for(int j=1; j<=i/2; j++)
    				dp[i] = Math.min(dp[j]+dp[i-j], dp[i]);
    		}
    	}
    	return dp[n]; 	
    }

}

Reference: