【问题标题】:Finding the median of two sorted arrays in logarithmic time在对数时间内找到两个排序数组的中位数
【发布时间】:2021-03-01 03:38:11
【问题描述】:

我试图理解this solution 寻找两个排序数组的中位数的问题:

public static double findMedianSortedArrays(int A[], int B[]) {
    int m = A.length;
    int n = B.length;

    if ((m + n) % 2 != 0) // odd
        return (double) findKth(A, B, (m + n) / 2, 0, m - 1, 0, n - 1);
    else { // even
        return (findKth(A, B, (m + n) / 2, 0, m - 1, 0, n - 1) 
            + findKth(A, B, (m + n) / 2 - 1, 0, m - 1, 0, n - 1)) * 0.5;
    }
}

public static int findKth(int A[], int B[], int k, 
    int aStart, int aEnd, int bStart, int bEnd) {

    int aLen = aEnd - aStart + 1;
    int bLen = bEnd - bStart + 1;

    // Handle special cases
    if (aLen == 0)
        return B[bStart + k];
    if (bLen == 0)
        return A[aStart + k];
    if (k == 0)
        return A[aStart] < B[bStart] ? A[aStart] : B[bStart];

    int aMid = aLen * k / (aLen + bLen); // a's middle count
    int bMid = k - aMid - 1; // b's middle count

    // make aMid and bMid to be array index
    aMid = aMid + aStart;
    bMid = bMid + bStart;

    if (A[aMid] > B[bMid]) {
        k = k - (bMid - bStart + 1);
        aEnd = aMid;
        bStart = bMid + 1;
    } else {
        k = k - (aMid - aStart + 1);
        bEnd = bMid;
        aStart = aMid + 1;
    }

    return findKth(A, B, k, aStart, aEnd, bStart, bEnd);
}

我无法理解的第一部分是 findKth 方法中定义的 aMid 和 bMid 如何表示 A 和 B 的中间计数。我手工浏览了几个示例,我可以看到,确实,在比较 A[aMid] 和 B[bMid] 之后,只剩下元素总数的一半。但是这两个索引的定义背后的想法是什么?为什么 A[aMid] 和 B[bMid] 比较后只剩下一半的元素?谁能解释一下这个解决方案?

【问题讨论】:

    标签: java algorithm


    【解决方案1】:

    假设 A[] = {1,5,6,7,8,9} 和 B[] = {2,3,4},那么 A[] 和 B[] 的中位数应该是 5,让我们浏览代码。

    1. findMedianSortedArrays(A, B), m=6, n=3
    2. findKth(A, B, 4, 0, 5, 0, 2)
      • aMid=6*4/(6+3)=2, bMid=4-2-1=1, 如a[2]=6>b[1]=3, 所以k=4-(1- 0+1)=2, aEnd=2, bStart=2
    3. findKth(A, B, 2, 0, 2, 2, 2)
      • aMid=3*2/(3+1)=1, bMid=2-1-1=0, 如A[1]=5>B[bMid+bStart]=B[2]=4, 所以k=2-(2-2+1)=1, aEnd=1, bStart=3
    4. findKth(A, B, 1, 0, 1, 3, 2)
      • bLen=0,返回 A[aStart+k]=A[0+1]=A[1]=5

    所以总体思路是:

    1. 根据数组长度的权重,得到数组可能的median。 (参考 aMid 和 bMid)
    2. 比较 A[aMid] 和 B[bMid],如果 (A[aMid] > B[bMid]),则表示:
      • 对于 B[bStart..bMid] 中的所有元素,它应该在中位数的左侧,这是容易的部分
      • 对于 A[aMid+1..aEnd] 中的所有元素,它应该位于中间值的右侧。这是因为 (aMid-aStart + bMid-bStart) 已经等于 (aLen+bLen)/2,并且在数组中位数左侧的 B[aMid+1..aEnd] 中可能有额外的元素。
      • 因此我们将两个数组都减小到一半大小,这就是运行时间复杂度应该为 O(log (m+n)) 的原因。
    3. 如此递归地找到 A[aStart..aMid] 和 B[bMid+1..bEnd] 中的中位数。

    【讨论】:

      【解决方案2】:

      java的基本方法;

      
        public double findMedianSortedArrays(int[] nums1, int[] nums2) {
              double res;
              int arr[] = new int[nums1.length+nums2.length];
              
              for(int i= 0; i<nums1.length; i++){            
                  arr[i] = nums1[i];
              }
              
              for(int i = nums1.length, j = 0; i<nums1.length+nums2.length; i++, j++){            
                  arr[i] = nums2[j];
              }
              Arrays.sort(arr);
              if(arr.length == 1)res = arr[0];
              else {
                  
                  if(arr.length % 2 == 0)res = ((arr[arr.length/2]+arr[(arr.length/2)-1])/2.0);
                  else{
                      res = arr[(arr.length/2)];
                  }
                  
              }
              
              return res;
              
          }
      

      【讨论】:

        猜你喜欢
        • 2014-10-12
        • 2011-07-22
        • 2014-08-02
        • 1970-01-01
        • 2013-09-18
        • 2014-03-18
        • 1970-01-01
        • 2014-10-25
        相关资源
        最近更新 更多