给定两个排序列表,每个包含n个实数,是否有一个O(log n)时间算法来计算两个列表的并集中排名i的元素(其中i对应于递增顺序的索引),假设两个列表的元素是不同的?
编辑: @BEN:这就是我一直在做的事情,但我仍然没有得到它。
我有一个例子;
列表A:1,3,5,7 清单B:2,4,6,8
查找等级(i)= 4。
第一步:i / 2 = 2; 列表A现在包含的是A:1,3 列表B现在包含的是B:2,4
compare A[i] to B[i] i.e
A[i] is less;
So the lists now become :
A: 3
B: 2,4
第二步: i / 2 = 1
List A now contains A:3
List B now contains B:2
NoW I HAVE LOST THE VALUE 4 which is actually the result ...
我知道我错过了一些东西,但即使在接近一天的思考之后我也无法想出这个......
答案 0 :(得分:8)
是:
您知道该元素位于第一个列表的索引[0,i]
或第二个列表的[0,i]
内。从每个列表中取元素i/2
并进行比较。一分为二。
我没有包含任何代码,因为这个问题听起来很像家庭作业。
编辑:二分法是二元搜索背后的方法。它的工作原理如下:假设i = 10; (基于零的索引,我们正在寻找整体的第11个元素。)
在第一步,您知道答案是在list1(0 ... 10)或list2(0 ... 10)中。取a = list1(5)和b = list2(5)。
如果是> b,然后list1中有5个元素位于a之前,而list2中至少有6个元素位于a之前。所以a是结果的上限。同样,list2中有5个元素位于b之前,而list1中小于6个元素位于b之前。所以b是结果的下限。现在我们知道结果是在list1(0..5)或list2(5..10)中。如果< b,然后结果在list1(5..10)或list2(0..5)中。如果a == b我们有答案(但问题是元素是不同的,因此a!= b)。
我们只需重复此过程,在每一步将搜索空间的大小减半。二分是指我们选择中间元素(平分线)超出我们知道的范围包括结果。
所以这个和二分法搜索之间的唯一区别是在二进制搜索中我们将比较我们正在寻找的值,但在这里我们将比较另一个列表中的值。
注意:这实际上是O(log i)
,它比O(log n)
更好(至少不会差)。此外,对于小i(可能是i <100),实际上合并第一个i元素(线性搜索而不是二分)的操作实际上更少,因为这样更简单。当您添加缓存行为和数据位置时,线性搜索可能会快速达到数千个。
此外,如果我&gt;然后依赖于结果必须朝向任一列表的末尾这一事实,每个列表中的初始候选范围来自((i-n).. n)
答案 1 :(得分:1)
这是你如何做到的。
让第一个列表为ListX
,第二个列表为ListY
。我们需要找到ListX[x]
和ListY[y]
x + y = i
的正确组合。由于x,y,i是自然数,我们可以立即将问题域约束为x*y
。通过使用公式max(x) = len(ListX)
和max(y) = len(ListY)
,我们现在需要搜索x*y
形式的[x, y]
元素子集。
您要做的是订购[i - max(y), max(y)]
,[i - max(y) + 1, max(y) - 1]
,...,[max(x), i - max(x)]
等元素。然后,您将通过选择中间[x, y]
组合来平分此列表。由于列表是有序且不同的,因此您可以测试ListX[x] < ListY[y]
。如果为真,则我们将[x, y]
组合的上半部分平分,或者如果为假,则将下半部分平分。你会保持一分为二,直到找到合适的组合。
我留下了很多细节,但这是它的一般要点。确实是O(log(n))!
编辑:正如Ben指出的那样O(log(i))
。如果我们让n = len(ListX) + len(ListY)
,那么我们就知道i <= n
。
答案 2 :(得分:0)
合并两个列表时,您将不得不触摸两个列表中的每个元素。如果你不触及每个元素,一些元素将被遗忘。因此,你的理论下限是O(n)。所以你不能这样做。
您不必排序,因为您有两个已经排序的列表,并且您可以将该排序维护为合并的一部分。
答案 3 :(得分:0)
编辑:oops,我误解了这个问题。我认为有价值,你想找到排名,而不是相反。如果您想查找给定值的排名,那么这是在O(log N)
中执行此操作的方法:
是的,如果列表允许O(log N)
随机访问(即它是一个数组而不是链接列表),则可以在O(1)
中执行此操作。
你必须计算出数学,+ 1,-1,如果找不到元素该怎么办等,但这就是想法。