【LeetCode】4. Median of Two Sorted Arrays

来源:互联网 发布:最好英语辅导软件 编辑:程序博客网 时间:2024/06/12 19:34

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)).

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个元素的值。

所以如果我们将两个元素直接合并乘一个数组,那么直接求取数组中下标为k-1的元素值,就是给定的结果。但是这种方法为O(m+n)。

当然,为进一步提高效率,我们可以考虑在merge的时候,并不是先生成新的数组,而是直接用两个指针分别指向两个数组的首部。并不断的推进两个指针,然后直到到达第k个元素上。

但是这种解法仍然为O(m+n)的时间复杂度。

这里记录了一种利用Binary Search的算法来确定第k个元素的值。

下面就是介绍下这种解法:

我们假设对于两个数组nums1和nums2的数组长度都大于k/2,所以我们可以获得nums1[k/2-1]和nums2[k/2-1]的数据值。注意下标为k/2-1的元素实际上是数组的第k/2个元素。

对这两个数据进行比较,我们可以得到有且只有如下三种情况:

  1. nums1[k/2-1] < nums2[k/2-1]
    在这种情况下,我们能够保证nums1[0]到nums2[k/2-1]之间的所有元素都是第k个元素之前的数值。

    因为对于nums1[k/2-1]而言,比它小的元素应该最多只有k/2-1 + k/2 -1 = k-2个。所以num1[k/2-1]至多是第k-1个元素。

    所以我们可以直接排除nums1[0]到nums1[k/2-1]之间的元素。

  2. nums1[k/2] > nums2[k/2]
    和情况1类似。

  3. nums1[k/2] == nums2[k/2]
    那么我们可以肯定num1[k/2]就是k个元素的值。

事实上,我们很多时候无法保证k能够刚好均分为两份,事实上这个时候,我们只要保证第一个数组的第i的元素和第二个数组的第j个元素相加之和为i+j=k,即可。具体原因可以自己思索一下。

class Solution {public:    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {        //求两个有序数组总的第k个数        int m = nums1.size(), n = nums2.size();        int k = (m+n)/2;        if((m+n) & 0x01)                return getTheKNumber(nums1,0,m,nums2,0,n,k+1);        else             return ((double)getTheKNumber(nums1,0,m,nums2,0,n,k) + getTheKNumber(nums1,0,m,nums2,0,n,k+1))/2;    }private:    int getTheKNumber(vector<int>& nums1,int ba,int ea,vector<int>& nums2,int bb,int eb,int k)    {        //保证nums1的查找长度始终小于等于nums2的查找长度。        if( (ea-ba) > (eb-bb) )            return getTheKNumber(nums2, bb, eb,nums1, ba, ea, k);        if(ba == ea)    return nums2[k-1];        if(k == 1)      return min(nums1[ba],nums2[bb]);        int pNums1 = min(ea-ba,k/2);        int pNums2 = k - pNums1;        if(nums1[ba+pNums1-1] < nums2[bb+pNums2-1])            return getTheKNumber( nums1, ba+pNums1, ea, nums2, bb, eb, k-pNums1);        else if(nums1[ba+pNums1-1] > nums2[bb+pNums2-1])            return getTheKNumber( nums1, ba, ea, nums2, bb+pNums2, eb, k-pNums2);        else             return nums1[ba+pNums1-1];    }};