C++ O(logn)算法在预排序列表的并集中查找秩为i的元素
给定两个排序列表,每个列表包含n个实数,是否有O(log n) 假设两个列表的元素不同,计算两个列表并集中秩i元素(其中i以递增顺序响应索引)的时间算法 编辑: @本:这就是我一直在做的,但我还是不明白 我有一个例子 清单A:1,3,5,7 清单B:2,4,6,8 求秩(i)=4 第一步:i/2=2; 列表A现在包含的是A:1、3 列表B现在包含的是B:2,4C++ O(logn)算法在预排序列表的并集中查找秩为i的元素,c++,algorithm,C++,Algorithm,给定两个排序列表,每个列表包含n个实数,是否有O(log n) 假设两个列表的元素不同,计算两个列表并集中秩i元素(其中i以递增顺序响应索引)的时间算法 编辑: @本:这就是我一直在做的,但我还是不明白 我有一个例子 清单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;
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 ...
我知道我遗漏了一些东西,但即使经过近一天的思考,我也不能只找出这一个…当合并两个列表时,您将不得不接触两个列表中的每个元素。如果你不去触摸每一个元素,一些元素就会落在后面。因此,你的理论下界是O(n)。所以你不能那样做 您不必排序,因为您有两个已经排序的列表,您可以在合并过程中保持排序 编辑:哎呀,我误解了这个问题。我认为给定值,你要找到等级,而不是相反的方法。如果您想查找给定的秩值,那么在
O(logn)
中就是这样做的:
是的,如果列表允许O(1)
随机访问(即它是一个数组而不是一个链表),则可以在O(log N)
中执行此操作
- L1上的二进制搜索
- L2上的二进制搜索
- 对指数求和
[0,i]
或第二个列表的[0,i]
中。从每个列表中提取元素i/2
,并进行比较。进行二等分
我没有包含任何代码,因为这个问题听起来很像家庭作业
编辑:二分法是二进制搜索背后的方法。它的工作原理如下:
假设i=10;(基于零的索引,我们正在寻找第11个元素)
在第一步中,您知道答案在列表1(0…10)或列表2(0…10)中。以a=list1(5)和b=list2(5)为例
如果a>b,则列表1中有5个元素位于a之前,列表2中至少有6个元素位于a之前。所以a是结果的上界。同样,列表2中有5个元素位于b之前,而列表1中少于6个元素位于b之前。所以b是结果的下界。现在我们知道结果在列表1(0..5)或列表2(5..10)中。如果a
我们只是重复这个过程,在每一步将搜索空间的大小减少一半。二分法是指我们在已知结果的范围之外选择中间元素(平分线)
所以这个和二进制搜索之间的唯一区别是,在二进制搜索中,我们比较我们要查找的值,但这里我们比较另一个列表中的值
注意:这实际上是O(logi)
比O(logn)
好(至少不差)。此外,对于小i(可能i<100),合并第一个i元素(线性搜索而不是二分法)的操作实际上会更少,因为这要简单得多。当您添加缓存行为和数据局部性时,线性搜索可能会更快,最多可达数千个
此外,如果i>n然后依赖于结果必须在两个列表的末尾这一事实,那么每个列表中的初始候选范围都是从((i-n)…n) 让第一个列表为
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]
,我们需要搜索
您将要做的是对这些元素进行排序,如so[i-max(y),max(y)]
,[i-max(y)+1,max(y)-1]
<代码>[max(x),i-max(x)]。然后,通过选择中间的[x,y]
组合,将此列表平分。由于列表是有序且不同的,因此您可以测试ListX[x]
。如果为真,则将组合的上半部分对分;如果为假,则将下半部分对分。你会一直平分直到找到正确的组合
我留下了很多细节,但这是主要的要点。它确实是O(log(n))
编辑:正如本所指出的,这实际上是
O(log(i))
。如果我们让n=len(ListX)+len(ListY)
那么我们知道i我从问题中收集到,他试图在索引i处找到值,所以他首先得到了一个索引,而不是一个要搜索的值,你可以将其向后搜索(问题是找到给定索引的值,而不是找到给定值的索引),但是使用二进制搜索是正确的。@Ben,@Phil:你说得对,我看错了。我仍然保留我的答案以供学习。您不必完成合并,因此它是O(I)
而不是O(n)
。但是你可以完全避免合并。+1!当然,列表必须允许O(1)
随机访问,但是是的,二进制搜索是关键。嘿,你能告诉我如何进行二分法吗。我是新来的,我在网上读到的大部分材料都与找到复杂的num的根有关