LeetCode4-两个排序数组的中位数

    对于单个数组的中位数很好求,如果个数是奇数则中位数为array[n/2],个数是偶数则中位数为(array[n/2]+array[n/2-1])/2。对于两个数组的中位数实际就是合并后数组的中位数,但是题目要求复杂度为O(log(m+n)),因此先合并再求中位数的方法放弃。可以从两数组的元素大小顺序入手,奇数数组是左中位数和右中位数和的一半,偶数数组的中位数就是右中位数(第n/2+1个数),因此只要找到从小到大第n/2+1个数就知道到了结果。

   假设数组a的长度和数组b的长度之和为k,则有以下关系:



将两数组都定位在k/2处,如果数组a[k/2-1]和数组b[k/2-1]相等,则两个合并的数组的第k个数就是在此位置。

如果a[k/2-1]比b[k/2-1]小,则第k个数在数组a的k/2处的右边和数组b的k/2处的左边范围,即图中红色的范围。

如果a[k/2-1]比b[k/2-1]大,则第k个数在数组a的k/2处的左边和数组b的k/2处的右边范围,即图中绿色的范围。

这种查找方法用到了二分查找的思想。

注意的问题是分割线的选择,如果数组a(默认它是较短的数组)的长度比k/2要小,则选择分割线就在数组a的最右边,即lengthOfArraya。

下面是代码实现,用时60ms

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
           int len1=nums1.size(),len2=nums2.size();
           int len=len1+len2;
           if(len%2==0)
           {
               return 0.5*(findKthVal(nums1,0,len1,nums2,0,len2,len/2)+
                           findKthVal(nums1,0,len1,nums2,0,len2,len/2+1));
           }
           else
           {
               return findKthVal(nums1,0,len1,nums2,0,len2,len/2+1);
           }
    }
    double findKthVal(vector<int>& nums1, int start1, int Length1, vector<int>& nums2, int start2, int Length2,int k)
	{
        if(Length1>Length2)  //确保nums1始终是较短的向量
            return findKthVal(nums2,start2,Length2,nums1,start1,Length1,k);
        
	    if(Length1==0&&Length2>0)
            return nums2[start2+k-1]; //如果nums1为空,则说明中位数就是nums2的第k个数
        if(k==1)  //这种情景对应nums1和nums2中参加比较的数的个数都为1,则左中位数就是两者中较小的一个
            return nums1[start1]<nums2[start2]?nums1[start1]:nums2[start2];
        
        int L1=Length1<k/2 ? Length1:k/2; //从中间位置开始二分查找
        int L2=k-L1;
        if(nums1[start1+L1-1]==nums2[start2+L2-1])
            return nums1[start1+L1-1];
        else if(nums1[start1+L1-1]<nums2[start2+L2-1])
            return findKthVal(nums1,start1+L1,Length1-L1,nums2,start2,L2,k-L1);
        else
            return findKthVal(nums1,start1,L1,nums2,start2+L2,Length2-L2,k-L2);
	}
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值