前のブログでは、暴力の問題への再帰的解決策が、解決策は分割統治について投稿しました。
最小限の問題に分解されるまで絶えず、ブレークダウンの問題を分割統治、そして、主要な問題の小さな表現の問題の解決のソリューションをバックアップし続けています。
まず、あなたが知る必要があるすべてのは、二分法は、分割統治の特殊なケースで、パーティションが等しい二項対立ではないということです。半分に、各計算で直接問題の規模を二分法。そして、通常のパーティションは、問題の全体的な規模を縮小しませんが、問題は、複数のサブ問題に分解されます。
次のように時間の複雑さが表現されています。
分割:O(1)の動作によっては、問題のnはN / 2の大きさの問題となるであろう。
T(N)= T(:すなわち N / 2)+ O(1)
パーティション:O(1)の動作によっては、問題のnにサイズ2 N / 2の問題となるであろう。
すなわち:T(N)= 2 T (N / 2)+ O(1)
ダウン再帰的:
部門:
T(N)= T(N / 2)+ O(1 ) T(N) = T(N / 4)+ 2 O(1 ) T(N) = T(N / 8)+ 3 O(1 ) ... ... [共logN個次] ... T(N) = T(1)+ logN個・O(1 ) T(N) = O(1)+ O(logN個)
T(N)= O(logN個)
分割統治:
パーティション1 T(N) = 2 T(N / 2)+ O(1 ) パーティション2倍 T(N) = 4 T(N / 4)+ 3 O(1 ) パーティション3倍 T(nは) = 8 T(N / 8)+ 。7 O(1 ) ... ... [logN個合計時間] ... T(N) =(N)T(1)+(N- 1)O(1 ) T(N) = * O N-(1)+ O(N- 1 )T (N) = O(N)+ O(N-1 ) T(N) = O(N)
バイナリ分割の特殊なケースであり、征服カット分岐されているように、単純に理解することができます。
同じサイズを発行し、音が分割統治に必要ではないようです。
しかし、我々は、再帰関数の分割統治の溶液に暴力的なソリューションを比較します。
暴力ソリューション:がsearch1(intは左、int型の半ば、int型の深さ)、モバイル検索回文文字列に頼る半ばでは、センターを後にしました。
パーティションソリューション:DPは(intは、int型の右を左)、左の決定 - 文字列が回文配列であるかどうかの間に右。次のように左右のIに設定されている、J、状態遷移方程式は次のとおりです。
暴力的な解決のために、我々は単にパラメータの関数に沿って解空間の探索にのみ、あなたが一時的な結果を保存し、その上に検索を調整することができ、Googleの検索をサポートできるようにする必要があり、それに加えて特別なセマンティックはありません。
私たちはアイデア分解問題、すべての関数呼び出しを持っているので、しかし、パーティション解決のために、それが問題の子を定義し、解決するために、です。参照コレクションに私たちは、サブ問題を定義するためのユニークな十分であり、我々は簡単にサブ問題の多くに必要なレベルの問題を見つけることができますので、私たちは、親と子の問題の問題の解決策との関係を定義する必要があります繰り返し。私たちは自然にキャッシュの確立のための座標の参照セットに、無効な計算を避けるためにすることができます。
実際には、ダブルカウントがたくさんある、私は暴力を探し、それを考えると、解空間のパーティションは基本的に同じです。
0 =左例ミッド= 3の場合、我々は、文字列がパリンドローム配列は、我々は、配列はパリンドローム配列が推定されている場合1 =左ミッド= 3に記載することができているかどうかを決定します。我々は、状態遷移方程式を定義していない。しかし、この繰り返し構造を見出すことは困難です。我々は明確に残され、半ば= 3の計算では、知覚することはできません= 1、その意味が何であるか、それは結果は、我々は一時的な結果をキャッシュする必要があるかどうか、再利用できるのかどうか。
問題のサブ分割、検索プロセスの計算のすべてのステップは、明確な定義を持っており、やみくもに計算を探していない私たちをみましょう。だから我々は、より簡単にダブルカウントを避けるために、解空間の繰り返し構造を見つけることができるという。
検索暴力と比較すると、問題と解空間の規模のパーティションのサイズには違いありません。私たちは限られた分割統治を検討するためしかし、十分な、ダブルカウントにこの利点を避けるために。
以下はleetcodeがで提出されている、コードのパーティションです。
パブリック 静的 ボイドメイン(文字列[]引数){ LongestSubStringさL = 新しいLongestSubString()。 文字列のソース =「babadada」。 System.out.println(l.longestPalindromeDP(ソース))。 } int型のmaxLength = 0 。 文字列ANS = "" ; 公共の 最終列longestPalindromeDP(文字列S){ もし、(S == NULL || s.length()== 0 ){ リターン "" 。 } int型の長さ= s.length()。 int型[] []キャッシュ= 新しい int型[長さ]、[長さ]; DP(S、 0、長さ- 1 、キャッシュ)。 もし(maxLengthの== 0 ){ 戻り s.substring(0、1 )。 } 戻りANS。 } プライベート 最終 ブール DP(文字列のソース、intは左、INT右、INT [] []キャッシュ){ 場合(左> = 右){ 戻り 真。 } であれば(キャッシュ[左] [右] == 1 ){ リターン 真; } であれば(キャッシュ[左] [右] == -1 ){ 戻り 偽。 } チャー leftChar = source.charAt(左)。 チャー rightChar = source.charAt(右)。 // 头尾不相等、尝试其它可能 であれば(leftChar =!rightChar){ DP(ソース、右、左 - 1 、キャッシュ)。 DP(左源、 + 1 、右、キャッシュ)。 キャッシュ[左] [右] = -1 ; リターン はfalse ; } //頭部および尾部は、それが文字列の先頭と末尾を除去サブパリンドローム配列かどうかが決定される、等しい ブール childIsSubstring = DP(ソース、+ 1つの左、右- 1。。 、キャッシュ); IF(== childIsSubstring 偽に){ DP(Sourceは、右、左 - 。1 、キャッシュ); DP(ソース、左 + 1 、右、キャッシュ)、 キャッシュ[左] [右] = -1 ; 戻り falseに; } // サブストリングストリングは直接、判定結果パリンドロームです。たとえそうであっても、他のを試してみてくださいする必要はありません、メインの文字列の長さよりも長くない、他のしてみてください。 INT右長= -左+ 1 ; IF(長さ> のmaxLength){ のmaxLength =長さ。 ANS = source.substring(左、右+ 1 )。 } キャッシュ[右] [左] = 1 。 返す 真; }