我正在尝试解决这个问题: nth smallest number among two databases of size n each using divide and conquer
据我所知,“比较中位数/中位数中位数”算法会给我们解决方案吗? 我的问题是我是否正确理解了这一点。
array 1: [7 8 6 5 3]
array 2: [4 10 1 2 9]
首先,找出每个的中位数。我们可以通过查询k = n / 2来做到这一点,其中n是该数组的大小。作为这种情况下的第三个最小元素,这为第一个数组提供了6个(调用此m1
),为第二个数组提供了4个(调用此m2
)。
从m1 > m2
开始,使用小于m1且大于m2的元素创建2个数组。
array 1: [5 3]
array 2: [10 9]
^ 我们如何找到小于m1且大于m2的元素?我们只需要取m1和m2并将它们与各自数组中的每个元素进行比较吗?我知道当两个数组都被排序时它会工作,但是首先对它们进行排序会让我们仍然得到O(log(n))查询吗?
我假设我们可以继续使用我们的特殊查询(可以吗?)来获取该特定数组的k = n / 2最小元素(中位数)。如果是这种情况,我们会查询k = n / 2 = 1,为我们留下新的m1 = 3
,m2 = 9
。
m1 < m2
,因此我们在该数组中使用大于m1且小于m2的元素制作2个数组。
由于数组2中没有小于m2 = 9
的元素,我们只留下一个数组,其中一个元素大于m1 = 3
。
[5]
&lt; - 这是中位数
我也有兴趣通过归纳看到正确性证明(这可以找到中位数)。
答案 0 :(得分:1)
中值算法的O(n)meidan实际上对数组进行了分区,使得前面的元素小于它,之后的元素大于它。
当你将中位数的中位数作为枢轴递归时,你正在对数组进行分区,使其看起来像
(小于中位数的元素) - p - (大于中位数的元素)
在正确性上,当您第一次查询k = n / 2时。得到m1和m2(m1> m2)。现在您知道有超过n个元素小于m1。所以跟随它的元素永远不会成为中位数的候选者 同样在m2之前的元素。它们之前有超过n个元素,所以它们永远不会成为中位数的候选者。所以中位数必须位于第二个数组的后半部分和第一个数组的前半部分。
但是现在当你递归时你应该记住你有第二个数组的n / 2个元素,所以你需要找到在两个数组的有序联合中占据第n / 2位置的元素(下半场和上半场)。
这似乎是渐近最优的,因为你总是将正在递归的数组的大小减少到一半。 类似于O(n)+ O(n / 2)+ O(n / 4)... = O(n)。
对于排序数组,您可以执行此操作是O(logn)。