在电话采访中我遇到了这个问题:
假设有一个范围列表。例如,[[1-6],[10-19],[5-8]]。 编写一个返回组合范围列表的函数 这样函数返回[[1-6],[10-19],[5-8]] [[1,8],[10,19]](仅限开始和结束编号)。注意,输入列表 可以包含任意数量的 的范围内。
我对此问题的解决方案是:
将所有范围列表合并到一个列表中: [[1-6],[10-19],[5-8]] - > [1-6,10-19,5-8]
在列表上执行排序: list = Sorted(list) - > [1,2,3,4,5,5,6,6,7,8,10 ...]
使用list = set(list)删除多余的数字
遍历列表并找到范围
我知道这个解决方案肯定是他们正在寻找的(这就是为什么我的采访非常失败)因为时间复杂度是O(nlogn)(排序),n是范围内不同数字的数量。
你能告诉python expert一个O(n)解决方案,n是原始列表中的范围数吗?
答案 0 :(得分:2)
您可以使用heapq
从范围创建堆。然后从堆中弹出范围,如果它与堆顶部重叠,则用合并范围替换顶部。如果没有重叠,或者没有更多的范围将其附加到结果:
import heapq
def merge(ranges):
heapq.heapify(ranges)
res = []
while ranges:
start, end = heapq.heappop(ranges)
if ranges and ranges[0][0] <= end:
heapq.heapreplace(ranges, [start, max(end, ranges[0][1])])
else:
res.append((start, end))
return res
ranges = [[1,6],[10,19],[5,8]]
print(merge(ranges))
输出:
[(1, 8), (10, 19)]
以上 O(n log n)时间复杂度, n 是范围数。
答案 1 :(得分:2)
首先,问题中提到的解决方案不是O(nlgn),其中n是段的数量。这是O(Xlg(X)),其中X = length of the segment*num of segments
非常慢。
存在O(NlgN)解,其中N是段的数量。
示例代码:
inp = [[1,6], [10,19], [5,8]]
inp = sorted(inp)
segments = []
for i in inp:
if segments:
if segments[-1][1] >= i[0]:
segments[-1][1] = max(segments[-1][1], i[1])
continue
segments.append(i)
print segments # [[1, 8], [10, 19]]
答案 2 :(得分:1)
如果范围是[x,y]和max_x,y可能在几百万之内,你可以做到这一点
我的想法是,我使用散列技术将它们排序,利用较低的max_y。
然后我们迭代并保持现有的“好”。范围是变量mn和mx。
当一个新范围出现时,如果它完全超出了“好”的范围。范围,我们追加良好的范围,并使新的范围作为良好的范围。否则我们会相应改变好的范围。
max_y = 1000000
range_sort = [None]*max_y
ranges = [[1,6],[10,19],[5,8]]
for r in ranges:
if range_sort[r[0]] is not None and range_sort[r[0]]>=r[1]:
continue ## handling the case [1,5] [1,8]
range_sort[r[0]] = r[1] # in the list lower value is stored as index, higher as value
mx = -1
mn = 1000000000
ans = []
for x,y in enumerate(range_sort): # The values are correct as explained in comment above
if y is None:
continue #To remove the null values
if x<mn:
mn = x # This will change the lower value of current range
if x>mx and mx>0: # If lower val x higher than current upper mx
ans.append([mn,mx]) # append current lower (mn) and upper(mx)
mn = x
mx = y # change the current upper and lower to the new one
if y>mx:
mx = y # This will change upper value of current range
ans.append([mn,mx]) # This has to be outside as last range won't get appended
print ans
输出:[[1,8],[10,19]]
时间复杂度 O(MAX_y)