arrays - 如何在两个排序数组的并集中找到第 k 个最小的元素?

标签 arrays algorithm binary-search divide-and-conquer

这是一道作业题,二分查找已经介绍过了:

Given two arrays, respectively N and M elements in ascending order, not necessarily unique:
What is a time efficient algorithm to find the kth smallest element in the union of both arrays?

他们说这需要 O(logN + logM),其中 NM 是数组的长度。

让我们将数组命名为ab。显然我们可以忽略所有 a[i]b[i] where i > k.
首先让我们比较一下 a[k/2]b[k/2]。让 b[k/2] > a[k/2]。因此我们也可以丢弃所有 b[i],其中 i > k/2。

现在我们有所有 a[i],其中 i < k 和所有 b[i],其中 i < k/2 可以找到答案。

下一步是什么?

最佳答案

我希望我不是在回答你的作业,因为这个问题被问到已经一年多了。这是一个尾递归解决方案,需要 log(len(a)+len(b)) 时间。

假设:输入正确,即 k[0, len(a)+len(b)] 范围内。

基本案例:

  • 如果其中一个数组的长度为 0,则答案为第二个数组的第 k 个元素。

减少步骤:

  • 如果 a 的中间索引 + b 的中间索引小于 k:
    • 如果a的中间元素大于b的中间元素,我们可以忽略b的前半部分,调整 k.
    • 否则,忽略 a 的前半部分,调整 k
  • 如果 k 小于 ab 的中间指数之和:
    • 如果 a 的中间元素大于 b 的中间元素,我们可以安全地忽略 a 的后半部分。
    • 否则,我们可以忽略 b 的后半部分。

代码:

def kthlargest(arr1, arr2, k):
    if len(arr1) == 0:
        return arr2[k]
    elif len(arr2) == 0:
        return arr1[k]

    mida1 = len(arr1) // 2  # integer division
    mida2 = len(arr2) // 2
    if mida1 + mida2 < k:
        if arr1[mida1] > arr2[mida2]:
            return kthlargest(arr1, arr2[mida2+1:], k - mida2 - 1)
        else:
            return kthlargest(arr1[mida1+1:], arr2, k - mida1 - 1)
    else:
        if arr1[mida1] > arr2[mida2]:
            return kthlargest(arr1[:mida1], arr2, k)
        else:
            return kthlargest(arr1, arr2[:mida2], k)

请注意,我的解决方案是在每次调用时创建较小数组的新副本,这可以通过仅传递原始数组的开始和结束索引轻松消除。

关于arrays - 如何在两个排序数组的并集中找到第 k 个最小的元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4607945/

相关文章:

javascript - 使用数组字符串寻找性能可行性

iphone - 同时在sqlite中填充数组

java - MFCC算法的三角窗如何生成以及如何使用?

c++ - 找出分数 a/b 的小数点后第 k 位,其中 a,b,k 是非常大的整数(小于 10e18)

algorithm - 具有两个 for 循环的该算法的时间复杂度

java - 根据要求具有多个键值的 Arrays.binarySearch

Javascript: 'new Array(4)' 与 Array.apply(null, {length: 4}) 有何不同?

c++ - 如何在 C++ 中返回一个整数数组

algorithm - 在 Go 中查找配对排列

data-structures - 链表中的二分查找