まず、以下のことは理論的な解決策であり、@MBoの提案を使用する必要があります。
ソートされた配列のすべての要素m = n/l
を取ります。長さがm
の同一の配列がi*m
と(i+1)*m
の間に適合できないので、これらの要素だけが重要となり得る。
各要素x
について、配列の下限と上限をバイナリ検索で検索します。インデックスを削除すると、カウントを知ることができ、x
を重要でないとみなしたり、破棄したりすることができます。
合計複雑度はO((n/m) * log n) = O(l * log n)
となります。 m
の場合、それはO(n)
より(漸近的に)良好であり得る。実際の改善を取得するには、しかし、あなたは非常に特殊な状況が必要になります。
あなたは(それがあまりにも可変幅のために可能であるが、いくつかの余分な努力が必要です)ソートされた固定幅の整数"data.bin"
からなるファイルがあるとします。あなたのファイルが(MBの数百)非常に大きい場合を除き、あなたは、最新のハードウェア上のナイーブO(n)
に比べて顕著な改善が得られないだろう、推測として
def find_all_important(l, n):
m = n/l
for i = m to l step m:
x = read_integer_at_offset("data.bin", i)
lower_bound = find_lower_bound(x, 0, i)
upper_bound = find_upper_bound(x, i, n)
if upper_bound - lower_bound >= m:
report(x)
def find_lower_bound(x, begin, end):
if end - begin == 0:
return begin
mid = (end + begin)/2
x = read_integer_at_offset("data.bin", mid)
if mid < x:
return find_lower_bound(x, mid + 1, end)
else:
return find_lower_bound(x, begin, mid)
:次に擬似コードでは、アルゴリズムは、そうのようなものである可能性があります。もちろん、データがRAMに収まらない場合は実行可能です。しかし、いつものように最適化はテストの価値があるかもしれません。
数字を保存するときにカウントを保存しないのはなぜですか?記憶は安いです。 –
同じ番号の実行が長い場合、バイナリ検索では、実行中のリニアスキャンよりも速く実行の終了を見つけることができます。もう一つのアイデアは、新しい番号に遭遇したときに、それが同じ番号であるかどうかを確認するために特定の距離をスキップすることができます。そうでない場合は、重要ではない(スキップされた番号は重要ではない)が、あなたがスキップした番号はそうかもしれない。 –