説明原題:
所与のn非負整数A1、A2、...、ポイント(iは、AI)各座標の数を表します。垂直座標内の動画n行、私は2つのエンドポイントは、(i、AI)及び(I、0)は垂直線です。x軸の構成は、水を収容できるように一緒に容器を有する2本のラインを見つけます。
注:あなたは、コンテナを傾けることができない、とnの値が2以上です。
オリジナルタイトルリンクします。https://leetcode-cn.com/problems/container-with-most-water
解決策1:暴力は解決します
暴力を解決している問題を解決するための最初のアイデアを取得するには。2つのサイクルを設定し、第一層は、高さを残した容器を横断するために使用され、第2の層の右側の高さは、容器を横断するために使用されます。次いで、不定詞は、(容器部)問題解決のサイズを比較している決定します。
側の配列を指定して、コンテナintで[]高さの高さを表して、私の思考プロセスは、次のとおりです。
1.二つの層は、ループ変数プレ(容器の高さの左側)および後(右のコンテナの高さ)を循環しています
それぞれ2つの境界ループ変数
事前<height.length-1 ポスト<height.length
容器無限大の面積の比較を決定3.
MAXSIZE = Math.max(MAXSIZE、(Math.min(身長[事前]、高さ[ポスト]))*(POST-PRE))。
各ループ、ループ変数の反復の終了前に再び4。右の高さにここに特別な注意が左側に基づいて反復の高さであります
次のように上記の分析を完了した後、我々は解決策を書くことができます。
1 公共 INT maxSizeの(INT []高さ){ 2 であれば(height.length <2 ||高== NULL ) 3 リターン 0 。 4 5 INT予備= 0、ポスト= 1 。 6 INT MAXSIZE = 0 。 7 一方(前<height.length-1 ){ 8 ながら(ポスト< height.length){ 9 MAXSIZE = Math.max(MAXSIZE、(Math.min(身長[事前]、高さ[ポスト]))*(ポスト- プレ))。 10 ポスト++ ; 11 } 12 プリ++ 。 13 ポスト=プリ+ 1 。 14 } 15 リターンMAXSIZE。 16 }
最初のパスの試運転、その後、2つのエラー:
1)ライン9比較コードは、両側の高さで発生する添え字の使用は、高さの値ではないということです。
2)、最初の4つの点、コード、すなわち13行を考慮していないので、長さの組み合わせのいくつかの能力の損失という。
対処方法2:ソリューションを最適化しよう(失敗しました)
2つのポインタが関連しているべきである。この問題を考えることは容易です。そして、二つのポインタが配列の左端から右にトラバースの終わりを考えるの慣性と一致している、という考えは、右ポインタトラバーサルは、比較領域の大きさの結果に応じて左ポインタも続く変化した場合に、適切な考慮すべきです。
私は3例を検討していました。
1)新分野横断コンテナ
INT SNEW =(Math.min(身長[事前]、高さ[ポスト]))*(POST-PRE)。
2)容器の隣接する領域の左側を検討
INT K =(身長[プレ+ 1]>高さ[事前])?(プリ+ 1):事前; //のための次 のint snext =(Math.min(高[K]、高さ[ポスト]))*(POST-K)。
3)最大範囲(左ポインタ)の容器左及び右辺に面積を考慮し
J =(高さ[ポスト]>高さ[J])?ポスト:J; //最高のための
int型SHIGH =(Math.min(高さ[J]、高さ[ポスト]))*(ポスト-J);
次いで、3例容器ステップ、反復左ポインタの領域の大きさを比較することによって。
IF(サイズ== snext && K =プリ!){事前++;} もし(!サイズ== SHIGH && J = PRE){プリ= J;}
ここでの問題は、隣接する要素の高さが等しい場合、そのときに暴力の通常のサイクルの代わりに使用した最初の(2)の場合は、使用して、解決することができるが、検討大きな試行の繰り返し方失敗します;
セクション(3)の場合を考慮したので、右ポインタの範囲内であるが、最大エッジ長として選び出し横断したこと、それが私に思われるこの時間は、それがサプリメントであるべきです。((3)がある場合は今だと思い、不要(2)はありません)
この質問を理解するので、私の考えは、右ポインタトラバーサルがケースは、コンテナの右側が含まれている関与していることを保証することができましたです。左側はちょうどあなたがコンテナの最大面積ことを確認することができ、現在のポインタトラバーサルの範囲についての最大の長さを見つける必要があります。
:次のようにソリューション
1 公共 INT maxSizeの(INT []高さ){ 2 であれば(height.length <2 ||高== NULL ) 3 リターン 0 。 4 5 INT予備= 0 。 6 INTポスト= height.length-1 。 7 INT MAXSIZE = 0 。 8 一方(前< ポスト){ 9 INT NewSizeパラメータ= Math.min(身長[事前]、高さ[ポスト])*(後PRE)。 10 MAXSIZE = Math.max(MAXSIZE、NewSizeパラメータ)。 11 であれば(高さ[事前]>高さ[ポスト]) 12 post-- 。 13 他 14 前++ ; 15 } 16 リターンMAXSIZE。 17 }
その後、試験試料中の[75,21,3,152,13,107,163,166,32,160,41,131,7,67,56,5,153,176,29,139,61,149,176,142,64,75,170,156,73,48,148,101,70,103,53,83,11,1 ...それは]の時間を与えています。私はその理由を推測、状況が不完全にしか横断することができます。
解決策3:2ポインタ(参照答え、その解決に失敗しました)
中間横断二重ポインタアレイの両端から公式回答。しかし、私は最も心配な状況のすべてへのアクセスを持って再びそこにトラバースされているかどうか?
私自身の考えは、モバイルからか、裁判官への各ポインタです。左ポインタで、例えば、1(高さ)の左ポインタ配列要素値未満の場合又は左ポインタ配列の要素の値に等しい、容器の幅全体が、元の面積より従って、必ずしも大きくないことができるが低減さを考慮。
ポインタが移動されるたびにすべての配列要素が中央に向かってポインター端部を横断するまで、したがって、特定の領域が大きくなります。しかし、この場合には、我々は......ポインタが動かないことがわかった後にポインタが移動しないように、考え、または配列要素を繰り返すことができるので。動きの大きさは、ここでは動作しませんもう一度確認を比較
コードは以下の通りであります:
1 公共 int型 solution4(INT []高さ){ 2 であれば(height.length <2 ||高== NULL ) 3 リターン 0 。 4 5 INT予備= 0 。 6 INTポスト= height.length-1 。 7 INT MAXSIZE = Math.min(身長[事前]、高さ[ポスト])*(後PRE)。 8 一方(前< ポスト){ 9 INT leftheight = Math.max(身長[事前]、高さ[プレ+ 1 ])。 図10は、 プレ=(身長[事前] <高さ[プレ+ 1])(プリ+ 1? ):事前。 11 INT rightheight = Math.max(身長[ポスト-1 ]、高さ[ポスト])。 12 ポスト=(身長[ポスト] <高さ[ポスト-1])(POST-1? ):ポスト。 13 INT NewSizeパラメータ= Math.min(leftheight、rightheight)*(後PRE)。 14 15 MAXSIZE = Math.max(MAXSIZE、NewSizeパラメータ)。 16 } 17 リターンMAXSIZE。 18 }
解決策4:2ポインタ(標準答え)
まず、公式のソリューションを貼ります:
1 公共 int型 solution3(INT []高さ){ 2 であれば(height.length <2 ||高== NULL ) 3 リターン 0 。 4 5 INT予備= 0 。 6 INTポスト= height.length-1 。 7 INT MAXSIZE = 0 。 8 一方(前< ポスト){ 9 INT NewSizeパラメータ= Math.min(身長[事前]、高さ[ポスト])*(後PRE)。 10 MAXSIZE = Math.max(MAXSIZE、NewSizeパラメータ)。 11 であれば(高さ[事前]>高さ[ポスト]) 12 post-- 。 13 他 14 前++ ; 15 } 16 リターンMAXSIZE。 17 }
それは分析を横断するダブルポインタを恐れているため、このような微細を検討するソリューション2つの理由は、常にいくつかの組み合わせが欠場することには十分ではありません。スリーおよびソリューションソリューションを感じる正式スタート理由が、ポインタ値、分析の不足の特定の感情の要素の詳細?
問題に別の解決策を読んで後、私はこのアイデアが完了したことがわかりました。
左ポインタとして定義されるI、および右ポインタJ、各場合(I、J容器の側面として両側)
2例、合計ので、3ノードを考えます
(1)は、最初の状況です
(2)手の動き、2つのノードが存在する、すなわち、左右の手の移動ポインタ移動(本質的に同じ) -
まず、左ポインタを考えます
$ H(I)<H(J)$場合、範囲のポインタ内の任意のノードkの周りに配置され、組み合わせ$ X = \ {(I、K)| I <K \ルJ \} $可能です除外。
例すべてを考えます
$ \ FORALL(I、K)\ Xは、H(I、K)= \ \左{\開始{アレイ} {1} {H(I)*(KI)、H(I)\当量のH(K )} \\ {H(K)*(KI)、H(I)> H(K)} \端{アレイ} \右。$
$ H(I)<H(k)に対する$、示されるように、あります
$ H(I)*(KI)\当量H(I)*(JI)$(赤色面積よりも小さい青色領域)
$ H(I)> H(k)の$のため、図示のように、あります
$ H(K)*(KI)\当量H(I)*(KI)<H(J)*(JI)$(面積よりも小さい青、赤領域)
要約すると、$ hの(I)<H(J)$、$ H(J)*(JI)$はまだたったの$ H(I + 1)?Hを見る必要があり、他のすべての組み合わせを包含/除外します安全に反復$ Iの$することができ、缶の場合(J)$、
$ I $反復後の面積が小さくなるが、トラバースを継続する領域のサイズを比較することによって、アルゴリズムを可能にするかもしれないが。
右手のために、同じような状況。従って、トラバースポインタの中間の左右両側に、全ての組み合わせを含んでいてもよいです。
要約:
- ダブルポインタ配列の両端から中間体溶液を横断するの基礎であります
- 場合によって実証可能なすべてが通過することができ、それは二重の指針に従って安全です