4. Median of Two Sorted Arrays

题目描述:

There are two sorted arrays nums1 and nums2 of size m and n respectively.

Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

You may assume nums1 and nums2 cannot be both empty.

Example 1:

nums1 = [1, 3]
nums2 = [2]

The median is 2.0
Example 2:

nums1 = [1, 2]
nums2 = [3, 4]

The median is (2 + 3)/2 = 2.5

解题思路:现在考虑一个更通用的问题:给定两个已经排好序的、从小到大排列的数组,找到两者所有元素中第k大的元素。假设两个数组A和B的元素个数都大于k/2,我们将A的第k/2个元素A[k/2-1]和B的第k/2个元素B[k/2-1]进行比较,有以下三种情况:

1. A[k/2-1] == B[k/2-1]

2. A[k/2-1] > B[k/2-1]

3. A[k/2-1] < B[k/2-1]

如果是A[k/2-1] < B[k/2-1],则可以进行如下的分析:

比A[k/2-1]小的元素的个数至多为 k/2-1+k/2-1=k-2 个,所以若将A和B合并为一个数组C,将C中的元素从小到大排列,则C的第k大的元素Ck一定在A[k/2-1]的右侧,即A的前k/2个元素一定不是Ck,可将它们排出搜索范围。

以此类推,若A[k/2-1] > B[k/2-1],则可将B的前k/2个元素排出搜索范围。

若A[k/2-1] == B[k/2-1],则A[k/2-1]或B[k/2-1]为第k大的元素。

以上分析都以k为偶数为前提,当k为奇数时,所得结论也是成立的。

参考代码:

double find_kth(std::vector<int>::const_iterator A, int m,
        std::vector<int>::const_iterator B, int n, int k) {
    double median;
    // always assume that m is equal or smaller than n
    if (m > n) {
        median = find_kth(B, n, A, m, k);
        return median;
    }
    if (m == 0) {
        median = *(B + k - 1);
        return median;
    }
    if (k == 1) {
        median = min(*A, *B);
        return median;
    }

    // divide k into two parts
    int ia = min(k / 2, m), ib = k - ia;
    if (*(A + ia - 1) < *(B + ib - 1)) {
        median = find_kth(A + ia, m - ia, B, n, k - ia);
        return median;
    }
    else if (*(A + ia - 1) > *(B + ib - 1)) {
        median = find_kth(A, m, B + ib, n - ib, k - ib);
        return median;
    }
    else {
        median = A[ia - 1];
        return median;
    }
}

double findMedianSortedArrays(const vector<int>& A, const vector<int>& B) {
    const int m = A.size();
    const int n = B.size();
    int total = m + n;
    double median;
    if (total & 1) {
        median = find_kth(A.begin(), m, B.begin(), n, total / 2 + 1);
        return median;
    } else {
        median = (find_kth(A.begin(), m, B.begin(), n, total / 2)
                + find_kth(A.begin(), m, B.begin(), n, total / 2 + 1)) / 2.0;
        return median;
    }
}

 

posted @ 2019-03-05 21:35  洗盏更酌  Views(115)  Comments(0Edit  收藏  举报