まず、「連続性」プロパティを無視しましょう
問題が1 つの個々の要求を処理する最も効率的な方法を見つけることに関するものである限り、単純な一般的な解決策は、2 つの連続するバイナリ検索を実行することです。順序。2 番目の検索は、配列の残りの部分、つまり、以前に検出されたシーケンスの先頭の右側で実行されます。
ただし、シーケンスの平均長が比較的小さいことが何らかの形でわかっている場合は、2 番目のバイナリ検索を線形検索に置き換えることが理にかなっています。(これは、同じような長さの 2 つの並べ替えられたシーケンスをマージするときに機能するのと同じ原理です。入力の構造により、検索のターゲットが平均してシーケンスの先頭近くに配置されることが保証されるため、線形検索はバイナリ検索よりも優れています)。
より形式的には、配列全体の長さが で、n
配列内の異なる整数値の数 (多様なメトリック) がk
である場合、 (実装に依存するいくつかの定数係数が実際的な関係を考え出す必要があります)。n/k
log2(n)
この効果を示す極端な例はn=k
、配列内のすべての値が異なる場合です。明らかに、線形検索を使用して各シーケンスの終わりを見つける (最初がわかれば) 方が、バイナリ検索を使用するよりもはるかに効率的です。
しかし、これには入力配列のプロパティに関する特別な知識が必要k
です。
そして、これが「継続性」プロパティの出番です!
数値は連続しているため、配列の最後の値から配列の最初の値を引いた値は に等しくk-1
、つまり、
k = array[n-1] - array[0] + 1
このルールは、元の配列の任意のサブ配列に適用して、そのサブ配列の多様性メトリックを計算することもできます。
これにより、シーケンスを見つけるための非常に実行可能で効率的なアルゴリズムが得られます。最初にシーケンスの先頭のバイナリ検索を実行し、次にとの間の関係に応じてバイナリ検索または線形検索を実行します。右サブアレイの多様性メトリックと右サブアレイの多様性メトリック)。n
k
PS同じ手法を最初の検索にも適用できます。のシーケンスを探している場合、それが配列内の - 番目i
のシーケンスであることがすぐにわかります。つまり、そのシーケンスの開始点の線形検索は、平均してステップを踏むことになります。この値が より小さい場合、二分探索よりも線形探索の方が適している可能性があります。j
j = i - array[0]
j * n/k
log2(n)