Algorithm 在2排序数组的并集中寻找第k个最小元素
我想这个问题被问了很多次,但仍然没有明确的答案! 无论如何,这就是我在O(k)中找到的好答案(也可能是O(logm+logn))。但我不明白,如果M_B>M_A(或其他方式),我们应该在M_B之后扔掉元素。但这里是在M_B之前的反向扔掉元素。有人能解释为什么吗 另一个问题是做K/2。。。我们应该这样做,但这对我来说并不明显 [编辑1]Algorithm 在2排序数组的并集中寻找第k个最小元素,algorithm,Algorithm,我想这个问题被问了很多次,但仍然没有明确的答案! 无论如何,这就是我在O(k)中找到的好答案(也可能是O(logm+logn))。但我不明白,如果M_B>M_A(或其他方式),我们应该在M_B之后扔掉元素。但这里是在M_B之前的反向扔掉元素。有人能解释为什么吗 另一个问题是做K/2。。。我们应该这样做,但这对我来说并不明显 [编辑1] Example A = [2, 9, 15, 22, 24, 25, 26, 30] B = [1, 4, 5, 7, 18, 22, 27, 33] k= 6
Example
A = [2, 9, 15, 22, 24, 25, 26, 30]
B = [1, 4, 5, 7, 18, 22, 27, 33]
k= 6
Answer is 9 (A[1])
下面是我的想法,如果我想在O(logk)中求解。。。每次需要抛出k/2个元素。
基本解决方案:如果K<2:从-A[0],A[1],B[0],B[1]返回第二小元素
其他:
比较A[k/2]和B[k/2]:如果A[k/2]B[k/2]做类似的事情)。所以现在的问题是下次k指数也是k还是k/2
我所做的是正确的?该算法并不坏——它比这里通常引用的算法好,所以,在我看来,因为它简单得多——但它有一个巨大的缺陷:它要求两个向量都至少有k
元素。(问题是它们都有相同数量的元素,n
,但从未指定n≥ k
;函数甚至不允许你告诉它向量有多大。但是,这很容易解决。我现在把它作为一个练习。一般来说,我们需要一个这样的算法来处理不同大小的数组,确实如此;我们只需要弄清楚先决条件。)
floor
和ceil
的使用既好又具体,但可能会让人困惑。让我们以最一般的方式来看一下。此外,引用的解决方案似乎假设数组是1索引的(即A[1]
是第一个元素,而不是A[0]
)。但是,我将要编写的描述使用了更类似C的伪代码,因此它假定a[0]
是第一个元素。因此,我将编写它以在组合集中查找元素k
,即(k+1)第
元素。最后,我要描述的解决方案与给出的解决方案有细微的不同,这在最终条件中会很明显。嗯,它稍微好一点
好的,如果序列中x
是元素k
,那么序列中正好有k
元素小于x
(我们不会处理重复元素的情况,但是没有太大的不同。参见注3。)
假设我们知道A
和B
都有一个元素k
(记住,这意味着它们都至少有k+1
元素)。选择任何小于k
的非负整数;我们称之为i
。并让j
为k-i-1
(这样i+j==k-1
)[参见下面的注释1.]现在,看看元素A[i]
和B[j]
。假设A[i]
更小,因为我们只需要在另一种情况下更改所有名称。请记住,我们假设所有元素都不同。现在我们知道:
1) A
中有i
元素,它们是
2) 在B
中有j
元素,它们是
3) A[i]
4) 从(2)和(3)中,我们知道:
5) 在B
中,最多有j
元素是
6) 从(1)和(5)中,我们知道:
7) A
和B
中最多有i+j
元素,它们是
8) 但是i+j
是k-1
,所以实际上我们知道:
9) 合并数组的元素k
必须大于A[i]
(因为A[i]
最多是元素i+j
)
因为我们知道答案必须大于A[i],所以我们可以通过[i]放弃[0](实际上,我们只是增加一个数组指针,但实际上我们会放弃它们)。但是,我们现在已经放弃了原始问题中的i+1
元素。因此,在新的元素集合中(在缩短的A
和原始的B
中),我们需要元素k-(i+1)
,而不是元素k
现在,让我们检查前提条件。我们说A
和B
都有一个元素k
元素,所以它们都至少有k+1
元素。在新问题中,我们想知道缩短的A
和原始的B
是否都至少有k-i
元素。显然B
确实如此,因为k-i
不大于k
。此外,我们还从A
中删除了i+1
元素。最初它至少有k+1
元素,所以现在它至少有k-i
元素。所以我们在那没问题
最后,让我们检查终止条件。一开始我说我们选择非负整数I
和j
,这样I+j==k-1
。如果k==0
,这是不可能的,但是对于k==1
,这是可以做到的。因此,我们只需要在k
达到0时执行一些特殊操作,在这种情况下,我们需要执行的是返回min(A[0],B[0])
。[这是一个比您所看到的算法中更简单的终止条件,请参见注释2。]
那么,挑选i
的好策略是什么呢?我们最终将从问题中删除i+1
或k-i
元素,我们希望这是尽可能接近一半的元素。所以我们应该选择i=floor((k-1)/2)
。虽然这可能不是立即发生的