Find the median of two sorted arrays(找到两个排好序的数组的中位数)

时间:2021-04-04 22:05:47

   原题是这样的:

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

这是leetcode中一道比较难的题目,因为他要求在log(m+n)时间内完成,一开始看到这道题的时候我首先想到的是先把两个数组合并,然后直接找出合并后的数组的中位数,但是这种方法的时间复杂度为O(m+n),太慢,因此,之后听老师讲了一遍这道题,又在网上找到了相关的资料,了解到这道题用分治算法解决可以达到log级的算法复杂度,基本思路就是比较nums1和nums2中间的元素的大小,然后根据情况删除掉nums1或nums2的一部分元素,假设nums1和nums2长度一样并且a为nums1的中位数,b为nums2的中位数,若a>b,则将比b小的那部分长度为L的元素删掉,然后在新的两个数组中继续找(nums1.size()+nums2.size())/2-L小的数即可,注意,这是不再是找中位数,而是找第k小的数,因此,我们首先得实现找第k小的数的函数findKth(),然后再根据两个数组的长度是奇数还是偶数调用findKth()找到中位数,再接下来就是具体的算法描述:

找到第k小的数(输入有A、B两个数组)findKth(vector<int> A,vector<int>B,int k):

 1、我们将长度比较小的数组A放在前面,方便比较;

 2、然后判断A数组的大小是否为0,是的话,返回B[k-1]即可;

 3、若k=1,则返回A[0]、B[0]之间的较小值;

 4、比较A数组大小n与k/2的大小,取较小的数a作为A数组元素的比较下标,以防k/2超过n,同时取k-a作为B数组的比较下标;

 5、若A[a]<B[K-a],则对A数组删掉a之前的元素,然后调用自身findKth(A,B,k-a);

 6、若A[a]>B[K-a],则对B数组删掉k-a之前的元素,然后调用自身findKth(A,B,a);

 7、若A[a]=B[K-a],直接返回A[a-1]即可。

然后对于找两个数组的中位数,则只需分两数组的和是奇数还是偶数,调用findKth即可。可以看出最坏情况下,每次数组的总长度都会减少1/4,因此复杂度为O(log(m+n)),具体代码实现如下:

class Solution {
public:
    double findKth(vector<int> nums1,vector<int> nums2,int k){
        int n1=nums1.size();
        int n2=nums2.size();
        if(n1>n2){
        return findKth(nums2,nums1,k);    
        }
        if(n1==0)
        return nums2[k-1];
        if(k==1)
        return min(nums1[0],nums2[0]);
        int a=min(k/2,n1);
        int b=k-a;
        if(nums1[a-1]<nums2[b-1]){
            nums1.erase(nums1.begin(),nums1.begin()+a);
            return findKth(nums1,nums2,k-a);
        }
        else if(nums1[a-1]>nums2[b-1]){
            nums2.erase(nums2.begin(),nums2.begin()+b);
            return findKth(nums1,nums2,k-b);
        }
        else
        return nums1[a-1];
    }
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int sum=nums1.size()+nums2.size();
        if(sum%2==1)
        return findKth(nums1,nums2,sum/2+1);
        else
        return (findKth(nums1,nums2,sum/2)+findKth(nums1,nums2,sum/2+1))/2.0;
    }
};