動態規劃專題:LeetCode 完全平方數

原題鏈接

279. 完全平方數

思路

這道題跟之前的動態規劃有些區別。刷了不少動態規劃的題目。大部分的結構,都是類似於這種形式

dp[i] = Math.max(min)(dp[i-n]+k, dp[i-m]+k1) + M

這種形式,涉及到最大小值,肯定涉及到題目求解的最值問題

而且一般絕大多數情況下是,時間複雜度都是O(n)。

這次的題目,主要涉及到一些關鍵點的處理。

如果不考慮這些關鍵點,無非就是

dp[i] 表示數字爲i的時候,最少的平方數字組成,也就問題所要的答案
dp[i] = dp[i-1] + 1(數字i-1加上1,就可以得到i)

關鍵點

不考慮平方數的時候,比如當 n = 4 的時候,dp[4] = dp[3]+1

但是如果考慮平方數的話,dp[4] = 2^2

然後就一直糾結關鍵點怎麼處理。看了題解,用了遍歷。

遍歷

for(int i = 1; i <= n; i++){
    dp[i] = n; // 等價 dp[i] = dp[i-1]+1;
    for(int j = 1; i-j*j>=0; j++){
        dp[i] = Math.min(dp[i], dp[i-j*j]+1);
    }
}

因爲無法判斷哪個數的平方可以滿足條件。所以需要去遍歷。比如對於 n = 4,需要去遍歷,4 - 1, 4 - 2^2。需要去取這些遍歷的最小值。

注意:因爲需要去取這些情況的最值,所以 min 必須含有其本身,所以這種結構,需要一開始去給dp[i]設置一個大的值,dp[i] = n只是這裏的特殊情況,其實 dp[i] = dp[i-1]+1 。是不考慮平方數所需最少的數,也就是dp[i]的上界。

如果還不是很清楚,舉個例子

dp[4] = min(dp[3]+1, dp[4-1]+1, dp[4-2^2]+1)
dp[10] = min(dp[9]+1, dp[10-1]+1, dp[10-2^2]+1, dp[10-3^3]+1)
拆解爲——————>
dp[4] = min(dp[3]+1, dp[4-1]+1)
dp[4] = min(dp[4], dp[4-2^2]+1)
----------->

只不過這個min中所含的參數個數是一直變化的,所以需要遍歷。

其次,因爲遍歷,所以一定要與之前求的值進行比較。所以需要在遍歷前進行初始化。

實現

class Solution {
    public int numSquares(int n) {
        int[] dp = new int[n+1];
        for(int i = 1; i <= n; i++){
            dp[i] = dp[i-1]+1;
            for(int j = 1; i-j*j>=0; j++){
                dp[i] = Math.min(dp[i], dp[i-j*j]+1);
            }
        }
        return dp[n];

    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章