O(n)
これは、0 の数に対する 1 の数を表す「高さ配列」を使用することで、非常に簡単に答えることができます。リンクされた質問の私の答えのように。
ここで、元の配列に焦点を当てるのではなく、 height によってインデックス付けされた 2 つの配列に焦点を当てます。一方には高さが見つかった最小のインデックスが含まれ、もう一方には高さが見つかった最大のインデックスが含まれます。負のインデックスは必要ないため、最小の高さが 0 になるようにすべてを上にシフトできます。
したがって、サンプル ケースの場合 (要点を示すために、最後にさらに 2 つの 1 を追加しました):
1110000011010000011111
配列の高さの視覚化
/\
/ \
/ \
\ /\/\ /
\/ \ /
\ /
\ /
\/
(最低の高さ = -5)
シフトされた高さ配列:
[5, 6, 7, 8, 7, 6, 5, 4, 3, 4, 5, 4, 5, 4, 3, 2, 1, 0, 1, 2, 3]
高さ: 0 1 2 3 4 5 6 7 8
first_view = [17,16,15, 8, 7, 0, 1, 2, 3]
last_view = [17,18,19,20,21,22, 5, 4, 3]
22 個の数字と 23 個の個別のインデックス (0 ~ 22) があることに注意してください。これは、数字の間の 23 個のスペースとパディングを表します。
first_view
とlast_view
配列を で構築できO(n)
ます。
ここで、 の各高さについて、 のfirst_view
より大きな高さをすべてチェックしlast_view
、インデックスとの差が最大のインデックスを取得するだけで済みfirst_view
ます。たとえば、高さ 0 から、より大きな高さのインデックスの最大値は 22 です。したがって、インデックス 17+1 で始まる最長の部分文字列は、インデックス 22 で終了します。
配列の最大インデックスを見つけるにはlast_view
、右の最大値に変換できますO(n)
。
last_view_max = [22,22,22,22,22,22, 5, 4, 3]
first_view
したがって、答えを見つけることは、単純にから減算することですlast_view_max
。
first_view = [17,16,15, 8, 7, 0, 1, 2, 3]
last_view_max = [22,22,22,22,22,22, 5, 4, 3]
結果 = [ 5, 6, 7,14,15,22, 4, 2, 0]
O(n)
そして、開始インデックス 0 から終了インデックス 22 まで、つまり文字列全体で達成された最大値 (再び ) を取得します。これは 22 です。=D
正当性の証明:
最大部分文字列が index で始まり、 indexi
で終わるとしますj
。index での高さが index での高さと同じである場合、i
要件を満たすより長い部分文字列になります。したがって、各高さの最初のインデックスを考慮するだけで十分です。最後のインデックスについても同様です。k<i
k..j