[LeetCode] 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)).

Subscribe to see which companies asked this question

Show Tags
 

分析:

这个题目在leetcode 中难度级别为hard。其实如果没有限定复杂度为O(log(m+n)),那么难度就要下降不少。

首先对于中位数这个概念,如果两个数组size 之和为奇数,那么中位数就是中间的那个数;否则中位数是中间两个数相加后的平均值。

  1. 比较容易想到的方法是采用merge sort 的方法合并两个数组,然后再取中位数,这样的时间复杂度在 O(m+n),不符合题目要求。其实merge sort 的策略只需要遍历((m+n)/2) 个数据就OK了,因为只需要早中位数,不需要完全遍历排序。
  2. 如果需要在O(log(m+n))下实现,就要考虑到这是个查找问题,对于有序数组的查找借助2分法的策略可以大大减去不必要的操作。这里借助在两个有序数组中find Kth 的思路。

关于两个有序数组的findKth,可以先比较两个数组A[m], B[n]的k/2位置,假设值为A[k/2 - 1] 和 B[k/2 - 1]:

  • 如果A[k/2 - 1] == B[k/2 - 1],那么就可以认为找到那个kth value;
  • 如果A[k/2 - 1] > B[k/2 - 1],那么可以判断出kth value 不处于B[0]到B[k/2 - 1],即可以去除掉这部分内容后,在剩下的内容中找到(k-k/2)th value;
  • 如果A[k/2] < B[k/2],就如同上一个条件一样,可以去除掉部分内容,重新调用findKth 策略.

最终演化为一个递归的策略,每次递归都可以去除一部分内容,并同时缩小K 的值,最终可以找到答案。

递归方案:

  • 当A 或 B 是空时,直接返回B[k-1] 或是 A[k-1]
  • 当k=1 时,返回 min(A[0], B[0])
  • 当A[k/2 - 1] == B[k/2 - 1] 时,返回A[k/2 - 1] 或 B[k/2 - 1]

note: findKth 的K是从1开始,而且要注意K与数组索引之间的关系,小心找到前一个或后一个位置。

 

实现代码:

Merge Sort 方案:

double merge(int *nums1, int nums1Size, int *nums2, int nums2Size)
{
    double result = 0.0;
    int totalSize = nums1Size + nums2Size;
    int mid = totalSize >> 1;
    int nums1Index = 0;
    int nums2Index = 0;
    int *nums = (int *)malloc((mid+1) * sizeof(int));
    
    for (int index = 0; index <= mid; index++) {
        if (nums1Index >= nums1Size) {
            nums[index] = nums2[nums2Index++];
        }
        else if (nums2Index >= nums2Size) {
            nums[index] = nums1[nums1Index++];
        }
        else if (nums1[nums1Index] < nums2[nums2Index]) {
            nums[index] = nums1[nums1Index++];
        }
        else {
            nums[index] = nums2[nums2Index++];
        }
    }
    
    if ((nums1Size + nums2Size) & 0x01) {
        result = nums[mid];
    }
    else {
        result = (nums[mid-1] + nums[mid])/2.0;
    }
    free(nums);
    return result;
}

double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) {
    return merge(nums1, nums1Size, nums2, nums2Size);
}            

  

FindKth 方案:

double findKth(int a[], int m, int b[], int n, int k) {
    if (m > n)  return findKth(b, n, a, m, k);
    if (m == 0) return b[k - 1];
    if (k == 1) return min(a[0], b[0]);
    
    int pa = min(k/2, m);
    int pb = k - pa;
    if (a[pa-1] < b[pb-1])  return findKth(a+pa, m-pa, b, n, k-pa);
    else if (a[pa-1] > b[pb-1])  return findKth(a, m, b+pb, n-pb, k-pb);
    else    return a[pa-1];
}

double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) {
    int mid = (nums1Size + nums2Size) >> 1;
    if ((nums1Size + nums2Size) & 0x01) {
        return findKth(nums1, nums1Size, nums2, nums2Size, mid+1);
    }
    else {
        return (findKth(nums1, nums1Size, nums2, nums2Size, mid)
                + findKth(nums1, nums1Size, nums2, nums2Size, mid + 1)) / 2.0;
    }
}

  

在Leetcode 中实际提交时,这两个方案都能达到最优的20ms 结果。

posted on 2016-06-13 17:40  chen-jiao  阅读(189)  评论(0编辑  收藏  举报