LeetCode11、最も水分の多い容器

1.直接的な思考方法

class Solution {
    
    
    public int maxArea(int[] height) {
    
    
        if(height==null||height.length==0||height.length==1){
    
    
            return 0;
        }
        int max=0;
       for(int j=0;j<height.length;j++)//起点
        {
    
    
            for(int i=1;i<=height.length-1;i++){
    
    //控制底边的长度。
            
                if(j+i<height.length){
    
    
                    int water = Math.min(height[j],height[j+i])*i;
                    if(max<water)
                        max = water;
                }else
                break;
            }

        }

    return max;
}
}

一度は受け入れますが、効率は次のとおりです。

ここに画像の説明を挿入
時間の複雑さがO(N 2)に達したことは間違いありません。

2.動的計画法

清華氏によると、動的な計画手順は次のとおりです。

  • 1.ステータスを確認する

状態を決定する鍵は
、最後のステップ見つけ、最後のステップから副問題の構造を導き出すことです。

この質問では、最終的な結果として、水を最大限に活用する2つのエンドポイント、ai、aj、およびresが見つかりました。それで、彼女の最後のステップは何でしたか?最後のステップでは、これらの2つのエンドポイントまたはエンドポイントの1つを探す必要があります。つまり、下付きの動きがあります。したがって、副問題があります。我们找当前的ai,aj,需要找到上一次的某两个端点a1,a2,她的盛水量不是最大的。(如何知道不是最大的,我们需要一个记录量,记录当前的最大量,即res)才会出现下标的移动。結果は次のとおりです。

    • (a[i],a[j])<-(a[i-1],a[j]),if(a[i-1]<a[j])
    • (a[i],a[j])<-(a[i],a[j+1]),if(a[i]>a[j+1])

したがって、a [i] [j]が計算されるとき、計算される現在の最大値はresであると推定できます。次に、resがグローバルな最大値であるかどうかを判断できません。他のエンドポイントの値を計算する必要があります。それで、添え字を移動する必要があります、それはそれを移動する方法ですか?height [i] <height [j]の場合、移動する添字はiでなければなりません。

含まれる水の量は、
2つのポインタが指す数値小さい方*ポインタ間の距離によって決定されるため
です。数字の大きい方のポインターを動かすと、前者の「2つのポインターが指している数字の小さい方の値」が増えず、後者の「ポインター間の距離」が短くなるため、この積が減ります。次に、それは最大量を見つけるための私たちの需要を満たしていません。したがって、数字が大きい方のポインタを動かすのは無理です。したがって、数字の小さい方にポインタを移動します。

状態を定義し、配列表現を開きます。特に、開かれた配列の次元とサイズも考慮する必要があります。

  • 2.再帰方程式
    res = min(res、(ji)* min(height [i]、height [j]));
  • 3.初期条件と境界条件
    初期条件は、この可能性があることですが、計算することはできず、同時に再帰に使用する必要があります。
    この質問には境界がありません。初期条件:水を保持するには2つのエンドポイントが必要です。したがって、height.length <= 1、-1を返します。
  • 4.計算シーケンス、つまり値を使用する場合、その必要性が導入されました。ここでは何も考慮しません

ここに画像の説明を挿入
上記の4つのステップを実行して初めて、コードの記述を開始できます。

class Solution {
    
    
    public int maxArea(int[] height) {
    
    
      if(height.length<=1)
        return -1;
        int i = 0,j=height.length-1,res = 0;
        while(i<j){
    
    
            int min = Math.min(height[i],height[j]);
            res = Math.max(res,(j-i)*min);
            if(height[i]<height[j]){
    
    
                i++;
            }else j--;
        }
        return res;
    }
}

公式ソリューション(デュアルポインタ方式)をご参照ください。動的プログラミングの扉に触れたのは初めてです。

おすすめ

転載: blog.csdn.net/qq_44861675/article/details/108367541