1. 程式人生 > >LeetCode-【動態規劃】-只有兩個鍵的鍵盤

LeetCode-【動態規劃】-只有兩個鍵的鍵盤

最初在一個記事本上只有一個字元 'A'。你每次可以對這個記事本進行兩種操作:

  1. Copy All (複製全部) : 你可以複製這個記事本中的所有字元(部分的複製是不允許的)。
  2. Paste (貼上) : 你可以貼上你上一次複製的字元。

給定一個數字 n 。你需要使用最少的操作次數,在記事本中打印出恰好 n 個 'A'。輸出能夠打印出 n 個 'A' 的最少操作次數。

示例 1:

輸入: 3
輸出: 3
解釋:
最初, 我們只有一個字元 'A'。
第 1 步, 我們使用 Copy All 操作。
第 2 步, 我們使用 Paste 操作來獲得 'AA'。
第 3 步, 我們使用 Paste 操作來獲得 'AAA'。

說明:

  1. n 的取值範圍是 [1, 1000] 。

題解:這道題可以轉化成,給一個數字N,初始K=1,C=0然後只允許你有兩種操作:  1、K = K + C (paste)  2 、C = K (copy all)  如何操作可以使得最快得到N,當N>1時,其實這道題就是將N分解為M個數字的乘積,並且使M最小。

比如:  2 = 1 * 1 = 2  3 = 1 * 1 *1 = 3  4 = 2 * 2 = 1* 1* 1 *1 =4 

class Solution {
    public int minSteps(int n) {
        int res=0;
        for(int i=2;i<=n;i++){
           while(n%i==0){
               res+=i;
               n=n/i;
           }
       }
       return res;
    }
}

動規解法:接著上面分析,可以看出最後的結果是目標值的約數乘積,我們想要得到目標值用約數的最小數目,那就設dp[i]為值為i的約數乘積最少數目,dp[i]由它的前一個狀態得到,那它的前一個狀態的表示是不是使用當前約數時的最優解,對應寫為dp[i/j]+j;所以動態轉移方程為dp[i]=max(dp[i],d[i/j]+j)。

class Solution {
    public int minSteps(int n) {
        if(n==1)
            return 0;
        int[] dp=new int[n+1];
        for(int i=1;i<=n;i++){
           dp[i]=i;
           for(int j=1;j<=(int)(Math.sqrt(i));j++){
               if(i%j==0)
                   dp[i]=Math.min(dp[i],dp[i/j]+j);
           }
        }
        return dp[n];
    }
}