python最小范围来自多个列表

时间:2016-08-08 19:26:28

标签: python algorithm list range

我需要使用每个列表中至少一个元素从一组整数列表中找到最小范围。

list1=[228, 240, 254, 301, 391]
list2=[212, 345, 395]
list3=[15, 84, 93, 103, 216, 398, 407, 488]

在此示例中,最小范围为[391:398],因为这涵盖了三个列表中的值391,395和398.

每个列表至少有一个值,可能还有更多列表

找到范围的最快计算方法是什么?

2 个答案:

答案 0 :(得分:5)

由于您的输入列表已排序,因此您可以使用合并排序,只需在合并的下一个值来自与上一个列表不同的列表时测试范围。跟踪您在每个列表上看到的最后一个值,并计算最低值和当前值之间的范围。这是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)

答案 1 :(得分:0)

当列表变得很大/很多时,此解决方案会显着减慢,但它并不假设输入列表是预先排序的:

end

<强> USAGE:

from itertools import product

def smallest_range(*arrays):

    result = min((sorted(numbers) for numbers in product(*arrays)), key=lambda n: abs(n[0] - n[-1]))

    return (result[0], result[-1])

list1 = [228, 240, 254, 301, 391]
list2 = [212, 345, 395]
list3 = [15, 84, 93, 103, 216, 398, 407, 488]

print(smallest_range(list1, list2, list3))

<强> PRINTS:

(391,398)