Leetcode 279.完全平方數
阿新 • • 發佈:2019-01-01
完全平方數
給定正整數 n,找到若干個完全平方數(比如 1, 4, 9, 16, ...)使得它們的和等於 n。你需要讓組成和的完全平方數的個數最少。
示例 1:
輸入: n = 12
輸出: 3
解釋: 12 = 4 + 4 + 4.
示例 2:
輸入: n = 13
輸出: 2
解釋: 13 = 4 + 9.
【思路】
1. 遞迴
對於一個數,我們怎麼求它的由哪些完全平方數相加得到的呢?
首先找到距離這個數最近的完全平方數m = x*x,我們從1~x中選擇一個數,求出n中包含z個x*x,我們在遞迴求出n-z*x*x所包含的完全平方數。遍歷1~x,返回其中最小的結果。
2. 動態規劃
動態規劃用 dp[i] 陣列儲存第 i 個數的完美平方數。遞推式為:dp[i] = Math.min(dp[j] + dp[i-j], dp[i]),認為 i 的完全平方數是從和為 i 的兩個完全平方數 dp[j] 和 dp[i-j]之和,然後從中取最小。
3. 改進後的動態規劃
如圖所示,紅色部分表示平方數,所有的數都可以看做一個普通數加上一個完美平方數,那麼遞推式就變為了:dp[i + j * j] = Math.min(dp[i] + 1, dp[i + j * j])。
【java遞迴實現】
1 publicclass Solution { 2 public int numSquares(int n) { 3 int count = n; 4 int nearest = (int)Math.sqrt(n); 5 if(n == 0) return 0; 6 if(nearest*nearest == n) return 1; 7 for(int i = nearest; i >= 1; i--) { 8 int cur = 0, num = n, t = i*i; 9while(num - t >= 0) { 10 num -= t; 11 cur++; 12 } 13 if(cur < count){ 14 count = Math.min(numSquares(num)+cur, count); 15 } 16 } 17 18 return count; 19 } 20 }
【java實現動態規劃】
1 public class Solution { 2 /* 3 動態規劃的思想來解決,遞推公式dp[i] = Math.min(dp[j] + dp[i-j], dp[i]) 4 */ 5 public int numSquares(int n) { 6 int[] array = new int[n+1]; 7 Arrays.fill(array, Integer.MAX_VALUE); 8 array[1] = 1; 9 10 for(int i = 2; i <=n; i++) { 11 int sqr = (int)Math.sqrt(i); 12 if(sqr*sqr == i) array[i] = 1; 13 else{ 14 for(int j = 1; j <= i/2; j++) { 15 array[i] = Math.min(array[j]+array[i-j], array[i]); 16 } 17 } 18 } 19 return array[n]; 20 } 21 }
【java實現改進後的動態規劃】
1 public class Solution { 2 /* 3 改進後動態規劃,遞推公式dp[i+j*j] = Math.min(dp[i]+1, dp[i+j*j]) 4 */ 5 public int numSquares(int n) { 6 int[] array = new int[n+1]; 7 Arrays.fill(array, Integer.MAX_VALUE); 8 9 for(int i = 1; i*i <= n; i++) { 10 array[i*i] = 1; 11 } 12 for(int i = 1; i <= n; i++) { 13 for(int j = 1; i+j*j <= n; j++) { 14 array[i+j*j] = Math.min(array[i]+1, array[i+j*j]); 15 } 16 } 17 return array[n]; 18 } 19 }