入力リストがソートされているので、マージソートを使用することができ、マージされる次の値が最後のリストと異なるリストから来たときに範囲をテストするだけで済みます。各リストで最後に確認した値を追跡し、最も低い値と現在の値の範囲を計算します。これはO(N)
線形時間アプローチです。ここで、N
はすべての入力リストの要素の合計数です。
アプローチ次実装:
def smallest_range(*lists):
iterables = [iter(it) for it in lists]
iterable_map = {}
for key, it in enumerate(iterables):
try:
iterable_map[key] = [next(it), key, it]
except StopIteration:
# empty list, won't be able to find a range
return None
lastvalues, lastkey = {}, None
candidate, candidatediff = None, float('inf')
while iterable_map:
# get the next value in the merge sort
value, key, it = min(iterable_map.values())
lastvalues[key] = value
if len(lastvalues) == len(lists) and lastkey != key:
minv = min(lastvalues.values())
difference = value - minv
if candidatediff > difference:
candidate, candidatediff = (minv, value), difference
lastkey = key
try:
iterable_map[key][0] = next(it)
except StopIteration:
# this iterable is empty, remove it from consideration
del iterable_map[key]
return candidate
デモ:リストは、多くの/大得るが、それはリストが事前にソートされた入力を負いませんので、このソリューションはかなり遅くなり
>>> list1 = [228, 240, 254, 301, 391]
>>> list2 = [212, 345, 395]
>>> list3 = [15, 84, 93, 103, 216, 398, 407, 488]
>>> smallest_range(list1, list2, list3)
(391, 398)
なぜそれが[391:395]ではないでしょうか? –
私は(395、398)が最も小さいと思います。 – ayhan
各リストの少なくとも1つの要素を使用する最小範囲は[391:398]です。 391、395、398を使用する – tagno25