我正在研究竞争性编程问题,我们试图找到两个排序数组的中位数。最佳算法是执行二进制搜索并识别两个数组之间的分裂点i
和j
。
我自己无法获得解决方案。我不明白最初的逻辑。到目前为止,我将按照我对这个问题的看法。
中位数的概念是将给定数组分成两组。合并两个给定的数组后,请考虑假设的left
数组和假设的right
数组。这两个数组的长度都相同。
我们知道给出这两个假设数组的中位数是[max(left) + min(right)]/2
。到目前为止这是有道理的。但是这里的问题现在知道如何构造left
和right
数组。
我们可以选择ArrayA
上的分割点i
和ArrayB
上的分割点j
。请注意len(ArrayB[:j] + ArrayB[:i]) == len(ArrayB[j:] +ArrayB[i:])
。
现在我们只需要找到切割点。我们可以尝试所有分裂点i
,j
,使它们满足中值条件。然而,这可能是O(m*n) where M is size of ArrayB and where N is size of ArrayA
。
我不确定如何使用我的思路来获得二元搜索解决方案的位置。如果有人能给我指点 - 那就太棒了。
答案 0 :(得分:2)
这是我设法提出的方法。
首先,我们知道结果数组将包含 N + M 元素,这意味着左侧部分将包含(N + M)/ 2 元素,并且右边的部分也包含(N + M)/ 2 元素。我们将结果数组表示为 Ans ,并将其中一个部分的大小表示为 PartSize 。
对阵列 A 执行二进制搜索操作。这种二分搜索的范围是[ 0 , N ]。此二进制搜索操作将帮助您确定阵列 A 中的元素数量,这些元素将构成生成数组的左部分。
现在,假设我们正在测试值 i 。如果 i 数组 A 中的元素应该包含在结果数组的左侧部分中,则表示 j = PartSize - i 元素必须包含在第一部分的 B 数组中。我们有以下可能性:
j> M 这是一个无效的状态。在这种情况下,这意味着我们仍然需要从数组 A 中选择更多元素,因此我们的新二进制搜索范围变为[ i + 1 , N ]
j< = M & A [i + 1]< B [j] 这是一个棘手的案例。想一想。如果数组 A 中的下一个元素小于数组 B 中的元素 j ,则表示元素 A [i + 1 ] 应该在左侧而不是元素 B [j] 。在这种情况下,我们的新二进制搜索范围变为[ i + 1 , N ]。
j< = M & A [i]> B [j + 1] 这与前一案例很接近。如果数组 B 中的下一个元素小于数组 A 中的元素 i ,则表示元素 B [j + 1] ] 应该在左侧而不是元素 A [i] 。在这种情况下,我们的新二进制搜索范围变为[ 0 , i-1 ]。
j< = M & A [i + 1]> = B [j] & A [i]< = B [j + 1] 这是最佳情况,您终于找到了答案。
二进制搜索操作完成后,您设法计算 i 和 j ,您现在可以轻松找到中位数的值。你需要在这里处理一些案例,具体取决于 N + M 是奇数还是偶数。
希望它有所帮助!