[解決済み】動的計画法を用いて,最も長く増加する部分列を決定する方法とは?
質問
整数の集合がある。を見つけたい。 最長増加部分配列 その集合の動的計画法を使って
どのように解決するのですか?
まず、最も簡単な解決策を説明しよう。これはO(N^2)であり、Nはコレクションの大きさである。また、O(N log N)の解も存在するが、これも説明する。見てください。 こちら の項を参照してください。
配列の添字を0からN - 1までとし、次のように定義します。
DP[i]
の要素で終わるLIS(Longest Increasing Subsequence)の長さです。
i
. を計算するために
DP[i]
のすべてのインデックスを調べます。
j < i
の両方をチェックし、もし
DP[j] + 1 > DP[i]
と
array[j] < array[i]
(増加するようにしたい)。もしこれが本当なら,現在の最適な
DP[i]
. 配列の全体最適を求めるには,配列の中の
DP[0...N - 1]
.
int maxLength = 1, bestEnd = 0;
DP[0] = 1;
prev[0] = -1;
for (int i = 1; i < N; i++)
{
DP[i] = 1;
prev[i] = -1;
for (int j = i - 1; j >= 0; j--)
if (DP[j] + 1 > DP[i] && array[j] < array[i])
{
DP[i] = DP[j] + 1;
prev[i] = j;
}
if (DP[i] > maxLength)
{
bestEnd = i;
maxLength = DP[i];
}
}
私は、配列
prev
これは、後で長さだけでなく実際のシーケンスを見つけることができるようにするためです。から再帰的に戻るだけです。
bestEnd
を使ったループで
prev[bestEnd]
. その
-1
の値は、停止を意味します。
さて、次はより効率的な
O(N log N)
の解決策になります。
Let
S[pos]
は、長さの増加する数列を終了する最小の整数と定義されます。
pos
. ここで、すべての整数
X
を入力し、次のようにします。
-
もし
X
の最後の要素です。S
を追加し、さらにX
の末尾にS
. これは本質的に、私たちが新しい最大のLIS
. -
の中で最も小さい要素を探します。
S
である。>=
よりX
に変更し、それをX
. なぜならS
はいつでもソートされるので、バイナリサーチを使って要素をlog(N)
.
総実行時間
N
整数とそれぞれのバイナリサーチ - N * log(N) = O(N log N)
では、実際の例をやってみましょう。
整数のコレクション。
2 6 3 4 1 2 9 5 8
ステップス
0. S = {} - Initialize S to the empty set
1. S = {2} - New largest LIS
2. S = {2, 6} - New largest LIS
3. S = {2, 3} - Changed 6 to 3
4. S = {2, 3, 4} - New largest LIS
5. S = {1, 3, 4} - Changed 2 to 1
6. S = {1, 2, 4} - Changed 3 to 2
7. S = {1, 2, 4, 9} - New largest LIS
8. S = {1, 2, 4, 5} - Changed 9 to 5
9. S = {1, 2, 4, 5, 8} - New largest LIS
つまり、LISの長さは
5
(Sの大きさ)。
を再構築するために、実際の
LIS
では、再び親配列を使用します。
では
parent[i]
をインデックスとする要素の前身である
i
の中で
LIS
をインデックスとする要素で終了します。
i
.
よりシンプルにするために、配列の中に
S
実際の整数ではなく、集合の中のインデックス(位置)です。我々は
{1, 2, 4, 5, 8}
を保持し
{4, 5, 3, 7, 8}
.
それは、input[4] = 1 入力[5]は 2 , input[3] = 4 , input[7] = 5 , input[8] = 8 .
親配列を適切に更新すれば、実際のLISは。
input[S[lastElementOfS]],
input[parent[S[lastElementOfS]]],
input[parent[parent[S[lastElementOfS]]]],
........................................
さて、肝心の親配列はどのように更新するのでしょうか?選択肢は2つあります。
-
もし
X
の最後の要素です。S
であればparent[indexX] = indexLastElement
. これは、最新の要素の親が最後の要素であることを意味します。私たちはただX
の末尾にあるS
. -
の最小の要素のインデックスを探します。
S
である。>=
よりX
に変更し、それをX
. ここでparent[indexX] = S[index - 1]
.
関連
-
[解決済み] どちらが大きいですか?O(log*n)とO(loglog n)
-
[解決済み] TSPの場合、Held-Karpアルゴリズムは、Brute-forceのO(n!)からO(2^n*n^2)に時間複雑性をどのように減少させるのでしょうか?[クローズド]
-
[解決済み] Sliding Window Algorithmとは?例題は?
-
[解決済み] O(log n)とは具体的にどういう意味ですか?
-
[解決済み] 山積みされた靴下を効率よく組み合わせるには?
-
[解決済み] 簡単な面接問題が難しくなった:1~100の数字が与えられたとき、ちょうどk個の数字が欠けていることを見つけなさい。
-
[解決済み】なぜBase64を使うのか?
-
[解決済み】メモライゼーションとダイナミックプログラミングの違いは何ですか?
-
[解決済み】背景色からフォントカラーを決定する方法
-
[解決済み】異なるサイズの長方形を、かなり最適な方法で可能な限り小さな長方形に詰め込むには、どのようなアルゴリズムが使用できるだろうか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 再帰の複雑さ T(n) = T(n-1) + T(n-2) + C
-
[解決済み] n個のユニオンのfind(サイズによるユニオン)演算を実行する際の時間計算量がO(n log n)であるのはなぜか?
-
[解決済み] バックトラックアルゴリズムの時間計算方法は?
-
[解決済み] 最大スパニングツリーの求め方は?
-
[解決済み】ある点が2次元の三角形の中にあるかどうかを判断する方法は?[クローズド]
-
[解決済み】与えられた和になるように数字の組み合わせの可能性を探す
-
[解決済み】動的計画法を用いて,最も長く増加する部分列を決定する方法とは?
-
[解決済み】ポリゴンの膨張・収縮(オフセット、バッファリング)のためのアルゴリズム
-
[解決済み】純粋な関数型プログラミングの効率性
-
[解決済み】固定長 6 int 配列の最速ソート