の場合にセグメントが有効であることを確認したあなたは正しいですmax(segment) - min(segment) + 1 = W
。したがって、問題は のすべての長さW
のセグメントの最小値と最大値を見つけることになりO(N)
ます。
このために、deque D
を使用できます。分を見つけたいとします。D
0 ベースのインデックス付けを想定して、要素のインデックスを に格納します。元A
の配列とします。
for i = 0 to N - 1:
if D.first() == i - W:
D.popFirst() <- this means that the element is too old,
so we no longer care about it
while not D.empty() and A[ D.last() ] >= A[i]:
D.popLast()
D.pushBack(i)
それぞれについて、これはindex の要素としてi
最小値を与えます。[i - W + 1, i]
D.first()
popFirst()
から最初の要素を削除しD
ます。の最初の要素がからステップD
以上W
離れてi
いる場合は、上記の間隔の最小値に寄与しないため、これを行う必要があります。
popLast()
から最後の要素を削除しD
ます。ソート順を維持するためにこれを行います。 の最後の要素がD
より大きい要素のインデックスである場合、 の最後A[i]
に追加すると順序が崩れます。したがって、ソートされた状態を維持するために、最後の要素を削除し続ける必要があります。i
D
D
pushBack()
の末尾に要素を追加しますD
。それを追加した後、D
間違いなくソートされたままになります。
これはO(1)
(min を見つけるため、上記の疑似コードは です) 各要素が最大 1 回O(n)
プッシュおよびポップされるためです。D
これD
は、常に 内の関連付けられた値でソートされたインデックスのスライディング ウィンドウになるため、機能しA
ます。この順序を破る要素にいる場合D
、順序が復元されるまで (スライディング ウィンドウ) から要素をポップできます。新しい要素はポップしている要素よりも小さいため、それらが解決に貢献できる方法はありません。
D
:start
とend
. _ 次にD
、長さの配列を作成N
すれば完了です。