【发布时间】:2013-10-10 15:59:20
【问题描述】:
几周前有人在这里发布了这个问题,但它看起来非常像没有事先研究的家庭作业,并且 OP 在获得了一些反对意见后立即将其删除。
不过,这个问题本身就很有趣,我已经考虑了一个星期,但没有找到令人满意的解决方案。希望有人可以提供帮助?
问题如下:给定N个整数区间的列表,其边界可以取从0到N³的任何值,找到最小整数i使得i不属于到任何输入间隔。
例如,如果给定列表 [3,5] [2,8] [0,3] [10,13] (N = 4) ,则算法应返回 9。
我能想到的最简单的解决方案运行在O(n log(n)),分为三个步骤:
- 通过增加下限对区间进行排序
- 如果最小下界>0,则返回0;
- 否则重复合并第一个区间和第二个区间,直到第一个区间(比如
[a, b])不接触第二个区间(比如[c, d])——也就是说,直到b + 1
- 返回
b + 1
这个简单的解决方案在O(n log(n)) 中运行,但原始发帖人写道,算法应该在O(n) 中运行。如果区间已经排序,这很简单,但是 OP 给出的示例包括未排序的区间。 我猜它一定与N³ 绑定有关,但我不确定是什么...散列?线性时间排序?欢迎提出想法。
这是上述算法的粗略python实现:
def merge(first, second):
(a, b), (c, d) = first, second
if c <= b + 1:
return (a, max(b, d))
else:
return False
def smallest_available_integer(intervals):
# Sort in reverse order so that push/pop operations are fast
intervals.sort(reverse = True)
if (intervals == [] or intervals[-1][0] > 0):
return 0
while len(intervals) > 1:
first = intervals.pop()
second = intervals.pop()
merged = merge(first, second)
if merged:
print("Merged", first, "with", second, " -> ", merged)
intervals.append(merged)
else:
print(first, "cannot be merged with", second)
return first[1] + 1
print(smallest_available_integer([(3,5), (2,8), (0,3), (10,13)]))
输出:
Merged (0, 3) with (2, 8) -> (0, 8)
Merged (0, 8) with (3, 5) -> (0, 8)
(0, 8) cannot be merged with (10, 13)
9
【问题讨论】:
-
我假设你的意思是非负整数,只有?
-
这里似乎有错误:
whose bounds can take any values from 0 to N³(0 而不是 1) -
"恒定时间排序?"没有没有这样的事情。即使在最好的情况下,对
n值序列进行排序也需要O(n)时间。您必须至少进行n-1比较以检查元素是否已排序。 -
您可以在 O(N) 时间内对 (0,N^3) 范围内的 N 个整数进行排序(假设每次比较花费恒定时间),使用 base-N 基数排序。
-
@Vincent 确实,0 不是 1,抱歉
标签: python algorithm big-o time-complexity intervals