在O(logN)中查找两个已排序数组的合并数组的中位数?

时间:2014-06-12 04:27:28

标签: arrays algorithm complexity-theory median

参考MIT handout

中的解决方案

我自己试图弄清楚解决方案,但我已经陷入困境,我相信我需要帮助才能理解以下几点。

  1. 在解决方案中使用的函数头

    MEDIAN -SEARCH(A [1。l],B [1。m],max(1,n / 2 - m),min(l,n / 2))

  2. 我不明白最后两个论点为什么不简单1,l为什么分别为max和min。

    1. 在pseduo代码中

      如果离开>右

      如果我们达到上述条件,为什么要切换A和B数组。

    2. 感谢你。

3 个答案:

答案 0 :(得分:1)

好吧,

left > right

然后,这意味着A中不存在中位数。因此,它必须存在于B中。因此我们切换。

例如,尝试计算

的算法
A = [ 1, 5] and B = [2, 3, 4]. 

现在,答案是3。 最初(左,右)是(1,3)。然后它变为(1,1)然后(2,1),我们切换A和B并继续B上的程序得到答案。

答案 1 :(得分:1)

MEDIAN-SEARCH(A[1..l], B[1..m], max(1, ceil(n/2)-m), min(l, ceil(n/2)))

maxmin来电限制了我们正在搜索的A区域。我们可以提前告诉我,如果某个数字位于ceil(n/2)-m中的A以下的位置,那么A的元素数量就会大于它的中位数。同样,位于ceil(n/2)之后的位置的数字大于A的太多元素而不是中位数。

如果left > right,那么二分搜索会减少我们搜索到的A段。切换AB表示我们开始搜索其他数组。

答案 2 :(得分:0)

我已经在JAVA中使用递归来实现它,该递归具有log(m + n)时间复杂度。

package FindMedianBetween2SortedArraysOfUnequalLength;

import java.util.Arrays;
import java.util.Scanner;

public class UsingKthSmallestElementLogic {

public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    try{
        System.out.println("Enter the number of elements in the first SORTED array");
        int n = in.nextInt();
        int[] array1 = new int[n];
        System.out.println("Enter the elements of the first SORTED array");
        for(int i=0;i<n;i++)
            array1[i]=in.nextInt();
        System.out.println("Enter the number of elements in the second SORTED array");
        int m = in.nextInt();
        int[] array2 = new int[m];
        System.out.println("Enter the elements of the second SORTED array");
        for(int i=0;i<m;i++)
            array2[i]=in.nextInt();
        System.out.println("Median of the two SORTED arrays is: "+findMedian(array1,array2,array1.length,array2.length));
    }
    finally{
        in.close();
    }
}
private static int findMedian(int[] a, int[] b,
        int aLength, int bLength) { 

    int left = (aLength+bLength+1)>>1;
    int right = (aLength+bLength+2)>>1;
    return ((findKthSmallestElement(a,b,a.length,b.length,left)+findKthSmallestElement(a,b,a.length,b.length,right))/2);
}
private static int findKthSmallestElement(int[] a, int[] b,
        int aLength, int bLength, int k) {                    // All the 5 parameters passed are VERY VERY IMP

    /* to maintain uniformity, we will assume that size_a is smaller than size_b
    else we will swap array in call :) */
    if(aLength>bLength)
        return findKthSmallestElement(b, a, bLength, aLength, k);

    /* We have TWO BASE CASES
     * Now case when size of smaller array is 0 i.e there is no elemt in one array*/
    //BASE CASE 1. If the smallest array length is 0
    if(aLength == 0 && bLength > 0)
            return b[k-1]; // due to zero based index

    /* case where k==1 that means we have hit limit */
    //BASE CASE 2. If k==1
    if(k==1)
            return Math.min(a[0], b[0]);

    /* Now the divide and conquer part */
    int i =  Math.min(aLength, k/2) ; // k should be less than the size of array  
    int j =  Math.min(bLength, k/2) ; // k should be less than the size of array  

    if(a[i-1] > b[j-1])
            // Now we need to find only K-j th element
            return findKthSmallestElement(a, Arrays.copyOfRange(b, j, b.length), a.length, b.length -j, k-j);
    else
            return findKthSmallestElement(Arrays.copyOfRange(a, i, a.length), b, a.length-i, b.length,  k-i);
}
}
/*
Analysis:
    Time Complexity = O(log(n+m))
    Space Complexity = O(1)*/