有没有办法避免对此进行线性搜索?

时间:2012-01-18 15:31:37

标签: python algorithm

我有一大堆具有起始编号和结束编号的对象。例如:

(999, 2333, data) 
(0, 128, data) 
(235, 865, data)
...

假设间隔彼此不重叠。我正在编写一个函数,它接受一个数字并找到(低,高)包含它的对象。说给出333,我想要列表中的第3个对象。

有没有什么方法可以尽可能有效地完成这项工作,缺少线性搜索?我在考虑二元搜索,但在处理范围检查方面遇到了一些困难。

4 个答案:

答案 0 :(得分:8)

想想是否值得对数据进行排序。
如果您只想搜索几次,那么它就不会 - 而且您无法避免线性搜索。搜索的总体复杂程度为O(n*k),其中n是元素数量,k是搜索次数。

如果您想要搜索很多次,那么您应首先排序,然后使用二进制搜索进行搜索。它将O(nlogn)用于排序,O(klogn)用于搜索k次,因此总共获得O((n+k)logn)

因此,只有k>=logn

才能进行排序和搜索

P.S。您可以使用其他方法进行排序和搜索,如其他答案中所提出的,在所有方面,结论仍然是:仅在k>=logn

时执行此操作

答案 1 :(得分:2)

您可以使用bisect模块:http://docs.python.org/library/bisect.html

您需要对数据进行一次排序,然后使用bisect:

import bisect
data=None
tuples=[(0, 128, None), (235, 865, None), (999, 2333, None)]
tuples.sort()
print tuples
print bisect.bisect(tuples, (-1,))   # 0
print bisect.bisect(tuples, (1,))    # 1
print bisect.bisect(tuples, (333,))  # 2
print bisect.bisect(tuples, (3333,)) # 3

答案 2 :(得分:2)

如果搜索速度至关重要,那么您可以创建一个查找表(已经由S.Lott评论过)。这将采用 O r )内存(其中 r 是范围的大小), O (< em> r )预处理时间, O (1)搜索时间。创建一个范围大小的数组,并使用指向数据的指针填充每个元素,或者为null。

lookup = {}
for low, high, data in source_ranges:
    for i in range(low,high): # or maybe high+1 if the ranges are inclusive
        lookup[i] = data

现在查找很简单。

答案 3 :(得分:1)

首先,完全不清楚二进制搜索是否合理。当间隔数量很小时,线性搜索可能会更快。

如果您担心性能问题,那么谨慎的做法是对代码进行分析,并对两种方法进行基准测试。

免责声明,二进制搜索可以通过对间隔进行一次排序,然后重复使用bisect模块进行搜索来实现:

import bisect

intervals = [(999, 2333, 'int1'), (0, 128, 'int2'), (235, 865, 'int3')]
intervals.sort()

def find_int(intervals, val):
   pos = bisect.bisect_left([interval[1] for interval in intervals], val)
   if pos < len(intervals) and val >= intervals[pos][0]:
      return intervals[pos]
   else:
      return None

print(find_int(intervals, 0))
print(find_int(intervals, 1))
print(find_int(intervals, 200))
print(find_int(intervals, 998))
print(find_int(intervals, 999))
print(find_int(intervals, 1000))
print(find_int(intervals, 2333))
print(find_int(intervals, 2334))

在上文中,我假设间隔不重叠,并且间隔包括其起点和终点。

最后,为了提高性能,可以考虑将[interval[1] for interval in intervals]从函数中分解出来并在开始时只执行一次。