Python 求排序数组并集的第k个最小元素
我正在研究关于在两个排序数组的并集中查找第k个最小元素的文章。我认为这个算法不正确。有这样一条线:我们观察到,当AiPython 求排序数组并集的第k个最小元素,python,algorithm,Python,Algorithm,我正在研究关于在两个排序数组的并集中查找第k个最小元素的文章。我认为这个算法不正确。有这样一条线:我们观察到,当Ai
i
和j
,这怎么可能是真的
第二,这句话也让我困惑:我们试图通过比较A和B的中间元素来解决这个棘手的问题,我们将其识别为Ai和Bj。如果Ai介于Bj和Bj-1之间,我们刚刚找到了i+j+1最小元素,尽管结果是真的。有人能解释原因吗?我真的很想理解这个算法,我通过合并数组完成了它,但这需要
O(N)
时间,而这里的O(logn)
时间。你是孤立地解释这些语句,但它们是相互建立的。以下是您(我认为)所指的文本:
保持不变量
i+j=k-1,
如果Bj-10
开始,但A0
是第一个最小项,A1
是第二个最小项,依此类推):
i+j=k-1
(定义不变)Bj-1
。那么Ai
必须是k
th最小值。这是因为Ai
大于A
中的i
项,大于B
中的j
项。因此它大于i+j=k-1
项的总和。这意味着它在合并的a | B
列表中的索引将是k-1
,因此它将是该列表中的第k
项李>
Ai-1
。然后,Bj
必须是第k
个最小值,与第2行的推理相同Bj-1
和(b)Ai-1
均为假。很明显,如果Ai
那么A1
,因为否则(a)是真的。同样,如果Bj
,那么Bj
,否则,(b)将为真Ai
时,Ai
一定是真的。另一方面,如果Bj
,则Bj
。。对于任何i
和j
,这怎么可能是真的
并非所有对i
和j
都是如此。这篇文章考虑了一种特殊情况
首先,假设不存在重复项,即使是以A
和B
的公共元素的形式。第二,结论是
Ai < Bj ==> Ai < Bj-1, resp. Bj < Ai ==> Bj < Ai-1
“排序数组的并集”,听起来像是
merge sort
@AshwiniChaudhary的merge
部分:我认为这个想法是,你得到两个排序数组,然后在不合并它们的情况下找到第k个最小的数组,因此取O(logn)
而不是O(n)
。这是解决这个问题的常用方法,但是与链接文章algo中的O(logn)
时间相比,它会产生O(N)
时间。等等,让我看看这是否足够!顺便说一下,谢谢!但是如果4中的两个断言是错误的,那么也有可能不是Ai
和A1
,Ai>Bj
?是的,我相信是这样。要点很简单,如果上面的(a)和(b)都为假,那么Ai要么高于Bj和Bj-1,要么低于两者;Bj也是一样。所以如果两者都有可能,为什么算法依赖于只有一个可能的事实?我不知道它如何依赖于只有一个可能的事实。我想这是基于这样一个事实:如果Ai
,那么Bj>Ai>Ai-1
,反之亦然。换句话说,两者都是可能的,但是如果一个适用于Ai,那么另一个适用于Bj。如果数组本身包含重复的元素,以及它们之间的重复元素(这些常见的重复元素本身可能在单个数组中重复),那么算法将受到怎样的影响?看起来相当复杂。即使你解释得很清楚,我也很难理解这个逻辑。你能建议一种不同的算法吗?你认为这是非常复杂的,还是我太笨了以至于无法理解?我添加了代码,这看起来太复杂了(与解释有关)?这需要一些时间才能让我明白。我的错,我刚刚开始习惯复杂的算法。是的,切片会增加额外的开销,因此应该使用索引来完成。这已经够复杂了,上帝只知道如果用索引代替切片会变成什么样子!
Bj-1 < Ai < Bj resp. Ai-1 < Bj < Ai
def kthsmallest(A, B, k):
if k < 1:
return None
a_len, b_len = len(A), len(B)
if a_len == 0:
return B[k-1] # let it die if B is too short, I don't care
if b_len == 0:
return A[k-1] # see above
# Handle edge case: if k == a_len + b_len, we would
# get an out-of-bounds index, since i + j <= a_len+b_len - 2
# for valid indices i and j
if a_len + b_len == k:
if A[-1] < B[-1]:
return B[-1]
else:
return A[-1]
# Find indices i and j approximately proportional to len(A)/len(B)
i = (a_len*(k-1)) // (a_len+b_len)
j = k-1-i
# Make sure the indices are valid, in unfortunate cases,
# j could be set to b_len by the above
if j >= b_len:
j = b_len-1
i = k-1-j
if A[i] <= B[j]:
if j == 0 or B[j-1] <= A[i]:
return A[i]
# A[i] < B[j-1] <= B[j]
return kthsmallest(A[i:], B[:j], k-i)
# B[j] < A[i], symmetrical to A[i] < B[j]
if i == 0 or A[i-1] <= B[j]:
return B[j]
# B[j] < A[i-1]
return kthsmallest(A[:i], B[j:], k-j)