【LeetCode】動的プログラミング研修(1)

面接の質問 08.01. 3 段階の質問

クリックして表示: 3 段階の質問

3段階の質問。子供が階段を上っています。階段には n 段あります。子供は一度に 1 段、2 段、または 3 段ずつ上がることができます。子供が何通り階段を上れるかを数えるメソッドを実装します。結果は非常に大きくなる可能性があるため、結果を 1000000007 で割る必要があります。

例 1:
入力: n = 3
出力: 4
説明: 移動方法は 4 つあります。
例 2:
入力: n = 5
出力: 13

トピック分析

n==1 の場合、
0 から 1、つまり 0->1 にしか進むことができないため、方法は 1 つだけです

n==2 の場合
、0->2 に移行できますが、
1->2 に移行する方法は 1 つあり、0 から 1 に移行する方法は 1 つだけで、1 から 2 に移行するのに必要なステップは 1 つだけです。 、
最終的に 1+1 には 2 つの方法があります。

n==3 の場合、
0->3 のメソッドは 1 つあります
。 1->3 では、0->1 のメソッドは 1 つしかなく、1 から 3 までは 1 ステップだけ必要なので、メソッドは 1 つだけです
。 2->3 、0->2 には 2 つのメソッドがあり、2 ~ 3 には 1 つのステップを追加するだけなので、2 つのメソッドがあり、
最後に 1+1+2 で合計 4 つのメソッドがあります。

n==4 の場合
、一度に実行されるステップは最大 3 つであるため、0->4 は無効です。1-
>4 の場合、0->1 にはメソッドが 1 つあるため、1 から 4 は追加するだけで済みます。 1 ステップなので、2->4 には 1 つのメソッドがあります。0->2 には 2 つのメソッドがあり、2 から 4 には 1 つのステップを追加するだけでよいため、0->3 であるため、3->4 には
2 つのメソッドがあります。
メソッドは 3 つあり、3 ~ 4 だけです。ステップを 1 つ追加する必要があるため、メソッドは 3 つあり、
最終的に 1+2+3 の合計 7 つのメソッドになります。


状態遷移方程式

位置 i で終了
dp[i] は、位置 i に到達するまでの方法が何通りあるかを表します。


状態遷移方程式
最新ステップの位置 i の状態で問題を分割

dp[i] は 3 つのケースで考慮されます。
i-1 位置から i 位置までは dp[i-1]
i-2 位置から i 位置までは dp[i-2]
i-3 位置から i 位置までは dp [i-3]

dp[i]= dp[i-1]+dp[i-2]+dp[i-3]

完全なコード

class Solution {
    
    
public:
    int waysToStep(int n) {
    
    
    if(n==1||n==2)
    {
    
    
        return n;
    }
    if(n==3)
    {
    
    
        return 4;
    }
    vector<int>dp(n+1);
    
    dp[1]=1;
    dp[2]=2;
    dp[3]=4;
    int i=0;
    for(i=4;i<=n;i++)
    {
    
    
        dp[i]=( (dp[i-1]+dp[i-2])%1000000007+dp[i-3])%1000000007;
    }
    return  dp[n];
    }
};

状態遷移方程式を計算する場合、3 つを加算してから係数を取得することはできません。そうしないと、エラーが報告されます。dp
[i-1] と dp[i-2] を加算する場合は、係数を取得する必要があります。次に、 dp[i-3 ] を使用し、追加するときに係数を取得します。


746. 最小限のコストで階段を登る

クリックして表示:最小限のコストで階段を登る

整数配列のコストが与えられます。ここで、cost[i] は、階段の i 番目のステップを上るコストです。この料金を支払うと、階段を 1 段か 2 段登るかを選択できます。
添字 0 または添字 1 の段から階段を登り始めるかを選択できます。
階段の一番上に到達するまでの最小コストを計算して返してください。

例 1:
入力: コスト = [10,15,20]
出力: 15
説明: 添字 1 のステップから開始します。
15を払って2段上の階段を上ります。
総コストは15です。

トピック分析

ここに画像の説明を挿入
下付き文字 0 から始めて、下付き文字 1 まで 10 元を費やすことも、下付き文字 2 に進むこともできますが、下付き文字 2 は
屋根ではありません。屋根の場合、最小コストは 10 でなければなりません。 15
なので、屋根はコスト配列の最後の要素の次になります。


下付き文字 1 の位置から開始して、下付き文字 2 の位置に行くことも、建物の屋上に行くこともできます

状態遷移方程式

dp[i] は位置 i に到達するときの最小コストを表し
、位置 i の最小コストは位置 i-1 の最小コストと位置 i-2 の最小コストを組み合わせて得られます。


dp[i] は次のように分割できます。

1. 最初に位置 i-1 に到達し、コスト [i-1] を支払い、1 歩進みます。
dp[i-1] は位置 i-1 に到達するための最小コストを表し、cost[i-1] は位置に必要なコストを表しますi-1、つまり
dp [i-1]+cost[i-1]

2. 最初に位置 i-2 に到達し、コスト [i-2] を支払い、2 歩進みます
dp[i-2] は位置 i-2 に到達するための最小コストを表し、コスト [i-2] は位置 i に必要なコストを表します-2
つまり、dp[i-2]+cost[i-2]

動的伝達方程式
dp[i]= min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);

完全なコード

class Solution {
    
    
public:
    int minCostClimbingStairs(vector<int>& cost) {
    
    
      vector<int>dp(cost.size()+1,0);
      dp[0]=0;
      dp[1]=0;
      int i=0;
      for(i=2;i<cost.size()+1;i++)
      {
    
    
          dp[i]=min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
      }
      return dp[cost.size()];
    }
};

状態遷移方程式では添字 0 と添字 1 の位置は使用できないためクロスボーダーが発生しますが、
問題では位置 0 または 1 から階段を登り始めることができます。つまり、2 つの位置は自由です。
つまり、dp [0 ] =0 、dp[1]=0

91. デコード方法

クリックして表示:デコード方法

文字 A ~ Z を含むメッセージは、次のマッピングによってエンコードされます。
'A' -> "1"
'B' -> "2"
'Z' -> "26"
エンコードされたメッセージをデコードするには、すべての数値が次のマッピングに基づいている必要があります。上記のマッピング方法、文字に戻す逆マッピング (複数の方法がある場合があります)。たとえば、「11106」は次のようにマッピングできます。
「AAJF」、メッセージを (1 1 10 6) としてグループ化
「KJF」、メッセージを (11 10 6) として
グループ化します。次の理由により、メッセージを (1 11 06) としてグループ化できないことに注意してください。 「6」と「06」はマッピングにおいて同等ではないため、「06」を「F」にマッピングすることはできません。
数値のみを含む空ではない文字列 s を指定した場合、デコード メソッドの合計数を数えて返します。
質問データは、回答が 32 ビット整数であることを保証します。

例 1:
入力: s = "12"
出力: 2
説明: "AB" (1 2) または "L" (12) としてデコードできます。

例 3:
入力: s = "06"
出力: 0
説明: 先行ゼロがあるため、「06」は「F」にマップできません (「6」と「06」は等価ではありません)。

トピック分析

1と2に分けるとそれぞれAとBに相当し、
全体で見るとLに相当します。


0 と 6 に分割した場合、0 には対応する文字がありません。
全体としてみなした場合、先頭の 0 は意味を示すことはできません。

状態遷移方程式

dp[i]はi位置が終了時のデコード方式の総数を示します。

ケース 1: 位置 i の数値を個別にデコードする

別途デコードされた数字は 1 ~ 9 である必要があるため、成功/失敗が発生します。

デコードが成功した場合、位置 i に対応する数値は 1 ~ 9 になります。これは、位置 0 ~ i-1 のすべてのデコード スキームの後に文字を追加することに相当し、デコードされた全体の数値は位置 i で終わる数値になります
。 -1 つまり、dp[i-1]

デコードが失敗した場合、すべて失敗し、デコード番号は 0 になります。
たとえば、60 は個別に計算され、6 は F、0 には対応する番号がないため、デコードは成功しません。

ケース 2: 位置 i の数値と位置 i-1 の数値を組み合わせてデコードします。

デコードが成功した場合、結合された数値は 10 ~ 26 になります。これは、位置 0 ~ i-2 のすべてのデコード スキームの後に文字を追加することに相当し、全体のデコード番号は i-2 で終わる数字になります
。つまり、dp [i-2]

デコードに失敗した場合はすべて失敗し、デコード番号は 0 になります。


dp[i]=dp[i-1]+dp[i-2]
dp[i-1]とdp[i-2]はデコードが成功した場合にのみ追加され、それ以外の場合は0になります。

完全なコード

class Solution {
    
    
public:
    int numDecodings(string s) {
    
    
       vector<int>dp(s.size());
        int i=0;

        //初始化
        if(s[0]!='0')
        {
    
    
            dp[0]=1;
        }
        else 
        {
    
    
            dp[0]=0;
        }
        
        //有可能s字符串只有一个数字 
        if(s.size()==1)
        {
    
    
            return dp[0];
        }

       if(s[0]!='0'&&s[1]!='0')
       {
    
    
           dp[1]++;
       }
       //因为s[0]存的是字符,所以选哟减去'0',从而获取数字
       int sum=(s[0]-'0')*10+(s[1]-'0');
       if(sum>=10&&sum<=26)
       {
    
    
           dp[1]++;
       }

        for(i=2;i<s.size();i++)
        {
    
    
            //说明可以单独编码成功
           if(s[i]!='0')
           {
    
    
             dp[i]+=dp[i-1];
           }

             //说明可以结合编码成功
            int sum=(s[i-1]-'0')*10+(s[i]-'0');
         
            if(sum>=10&&sum<=26)
            {
    
    
                dp[i]+=dp[i-2];
            }

        }
        return dp[s.size()-1];
    }
};

dp[0]を初期化すると
、数値が 1 つだけであることを意味します。
数値が 1 ~ 9 の場合、デコードは成功し、1 が返されます。
数値が 0 の場合、デコードは失敗し、0 が返されます。

dp[1] は、2 つの数値を
2 つの数値に分割し、それらを個別にデコードし、組み合わせてデコードできることを意味します。

単独でデコードが成功した場合はデコード番号+1、それ以外は0、
組み合わせが成功した場合はデコード番号+1、そうでない場合は0なので、
0・1・2の3通りになります。

おすすめ

転載: blog.csdn.net/qq_62939852/article/details/131345265