[英]Finding the kth-smallest element in union of sorted arrays
我正在研究关于在leetcode中找到两个排序数组的并集中的第k个最小元素的文章。 我不认为算法是正确的。 有这条线: 我们观察到当Ai <Bj时,那么Ai <Bj-1必定是真的。 另一方面,如果Bj <Ai,则Bj <Ai-1。 。 对于任何i
和j
它怎么可能都是真的?
其次,这条线也让我困惑: 我们试图通过比较A和B的中间元素来解决这个棘手的问题,我们将其识别为Ai和Bj。 如果Ai在Bj和Bj-1之间,我们刚刚找到了i + j + 1最小元素 ,尽管它是真实的。 任何人都可以解释原因吗? 我真的想要理解算法,我已经通过合并数组来完成它,但是这需要O(N)
时间,而这里需要O(log N)
时间。
你是孤立地解释这些陈述,但它们是相互依赖的。 这是(我认为)你所指的文字:
维持不变i + j = k - 1,如果Bj-1 <Ai <Bj,那么Ai必须是第k个最小的,否则如果Ai-1 <Bj <Ai,那么Bj必须是第k个最小的。 如果满足上述条件之一,我们就完成了。 如果没有,我们将使用i和j作为细分索引来细分数组。 但是怎么样? 我们应该丢弃哪部分? 艾和Bj本身怎么样?
我们观察到当Ai <Bj时,那么Ai <Bj-1必定是真的。 另一方面,如果Bj <Ai,则Bj <Ai-1。 为什么?
将其分解为子命题会产生以下解释(请记住,索引从0
开始,但A0
是第一个最小项, A1
是第二个最小项,依此类推):
i + j = k - 1
(根据定义不变) Bj-1 < Ai < Bj
。 然后Ai
必须是最小的第k
个。 这是因为Ai
大于A
i
项并且大于B
j
项。 所以它总共大于i + j = k - 1
项。 这意味着它在合并的A|B
列表中的索引将是k - 1
,因此它将是该列表中的第k
个项目。 Ai-1 < Bj < Ai
。 那么Bj
必须是第k
个最小的,通过2中相同的推理线。 Bj-1 < Ai < Bj
和(b) Ai-1 < Bj < Ai
都是假的 。 然后很明显,如果Ai < Bj
则A1 < Bj-1
,否则(a)将成立。 同样,如果Bj < Ai
然后Bj < Ai-1
,否则,(b)将是真的。 我告诉你,你想要解释这些陈述而不是整个算法。 (但如果你愿意,我会说更多。)
还要注意,正如Daniel Fischer的回答提醒我的那样,只有没有重复的情况下,上述推理才有效; 称这个命题为0。
我们观察到当
Ai < Bj
,那么Ai < Bj-1
必定是真的。 另一方面,如果Bj < Ai
,那么Bj < Ai-1
..对于任何i
和j
它怎么可能是真的?
对于所有i
和j
对都不是这样。 文章考虑了一个特殊情况。
首先,假设没有重复,甚至没有A
和B
的共同元素的形式。 第二,结论是
Ai < Bj ==> Ai < Bj-1, resp. Bj < Ai ==> Bj < Ai-1
是在两者都没有的条件下制造的
Bj-1 < Ai < Bj resp. Ai-1 < Bj < Ai
成立。 因此,通过排除这些配置, Ai < Bj ==> Ai <= Bj-1
并且Bj < Ai ==> Bj <= Ai-1
立即跟随,然后严格的不等式遵循假设不存在重复。
我们试图通过比较A和B的中间元素来解决这个棘手的问题,我们将其识别为Ai和Bj。 如果Ai在Bj和Bj-1之间,我们刚刚发现i + j + 1最小元素
在阵列B
,存在小于Bj
j
元素,并且在阵列A
,存在小于Ai
i
元素(索引从0开始)。 因此,如果Bj-1 < Ai < Bj
,则两个阵列一起恰好包含小于Ai
j + i
元素。
不多。
我们仍然考虑i + j = k-1
。 我们假设Ai <= Bj
。
Ai = Bj
怎么办? Ai < Bj
怎么办? 在情况1中,令m
为最小索引,使得Am = Ai
,并且n
为最小索引,使得Bn = Bj
。 然后在两个阵列中,恰好m + n <= i + j = k-1
元素严格小于Ai
,并且至少(i+1) + (j+1) = (k+1)
元素不大比Ai
。 因此,第k个最小元素等于Ai
。
对于2.,我们有三种情况要考虑,a) Bj-1 < Ai
,b) Bj-1 = Ai
,c) Bj-1 > Ai
。
在a)的情况下,我们在B
中有不大于Ai
j
元素,并且它们都严格地小,并且我们在A
中有m <= i
元素,它们严格小于Ai
( m
如上)和未知数字,但至少i-m+1
元素等于Ai
。 因此,两个阵列中的j + m <= j + i = k-1
元素恰好小于Ai
,并且至少j + m + (i-m+1) = j+i+1 = k
元素不大于Ai
,因此两个数组的第k个最小元素一起等于Ai
。
在情况b)中,相同的推理表明两个阵列的第k个最小元素一起等于Ai
。
在剩下的情况下, Ai < Bj-1
,事情变得不复杂了。 数组B
至少包含不大于Bj-1
j
元素,并且数组A
至少包含严格小于Bj-1
i+1
元素,因此两个数组的第k个最小元素一起最多与Bj-1
一样大Bj-1
。 但它不能比较小Ai
( B
含有至多j-1
更小的元素比Ai
,因此两个阵列一起含有至多i + (j-1) = k-2
小于元件Ai
)。
因此,我们仍然可以从阵列A
丢弃Ai
下面的部分,从阵列B
丢弃Bj-1
上面的部分,并且不重复。
所有改变的是,一些严格的不平等必须被弱的不平等所取代。
代码(如果传递索引和长度而不是切片会更有效,但切片会产生更短的代码):
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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.