leetcode No4. Median of Two Sorted Arrays

Question:

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

求两个数组合并后的中位数

Algorithm:

中位数求法:把长度为k数组从小到大排列,返回中间位置的元素。
k为奇数,中位数为nums[k/2],k为偶数中位数为(nums[k/2]+nums[(k/2)-1]/2
算法1:归并两个数组后,找中位数,复杂度O(m+n)
算法2:类似二分查找,不需要归并,复杂度O(log(m+n))
现在详细说明解法2,我们可以把问题转化为寻找第k大的元素
假设AB的长度都大于k/2,比较A[(k/2)-1]和B[(k/2)-1],有三种情况
1、A[k/2-1] = B[k/2-1]
此时,我们就已经找到第k大的元素,即element=A[k/2-1]=B[k/2-1]
2、A[k/2-1] < B[k/2-1]
此时,意味着A[0]~A[k/2-1]都比第k个元素小,因为A[0]~A[k/2-1]有k/2个元素,B[0]~B[k/2-1]有k/2个元素,如果A[k/2-1]是比第k个元素还大的元素,假设A[k/2-1]是比第k+1小的元素,那么B[k/2-1]至少是第k+2大的元素。但是在A中至多有k/2-1个元素小于A[k/2-1],在B中至多有k/2-1个元素小于A[k/2-1],总共至多有(k/2-1+k/2-1)即k-2个元素。所以A[k/2-1]不可能大于第k个元素。所以我们可以删去,然后找第k-k/2=k/2个元素。
3、A[k/2-1] > B[k/2-1]
类似2
在这里要注意三种特殊情况
1、如果AB有一个是空,则返回非空数组下标为k-1的元素,即A[k-1]或B[k-1]
2、如果k==1,则返回min{A[0],B[0]}
3、如果k/2比短的数组长的话(假设是A),则比较A[m-1]和B[k/2-1]
Ex:
A{1,3,7,8}     m1=4
B{2,4,5,6,7,8,9,10,12}   m2=9
由于删除元素较为麻烦,所以在程序中设两个变量begin1,begin2作为起始元素。再设置m1和m2作为有效数组长度。
1、合并后的数组,长度为m1+m2=13,那么我们要找出第13/2+1=7,即k=7,第7大的元素。刚开始begin1和begin2都为0,m1=4,m2=9
2、A[begin1+k/2-1]=A[2]=7 > B[begin2+k/2-1]=B[2]=5,所以我们删去B中的2,4,5,在程序中,我们可以使begin2指针指向元素6,即begin2=3,m2=9-3=6,现在我们要找出k-3即第4大的元素
3、k=4,begin1=0,begin2=3,m1=4,m2=6,A[begin1+k/2-1]=A[1]=3 < B[begin2+k/2-1]=B[7],所以我们删去A中1,3,begin1=0+2=2,m1=4-2=2,现在我们要找出k-2,即第2大的元素
4、k=2,begin1=2,begin2=3,m1=2,m2=6,A[begin1+k/2-1]=A[2]=7 > B[begin2+k/2-1]=B[3]=6,所以我们删去B中6,begin2=3+1=4,m2=6-1=5,现在我们要找出k-1,即第1大的元素
5、k=1,begin1=2,begin2=4,m1=2,m2=5比较A[begin1]=A[2]=7,B[begin2]=B[4]=7,返回7,最终结果为7

Accepted Code:

算法1:
class Solution {
public:
    vector<int> MergeSort(vector<int>& nums1, vector<int>& nums2)
    {
        vector<int> res;
        int i=0,j=0;
        while(i<nums1.size() && j<nums2.size())
        {
            if(nums1[i]<=nums2[j])
            {
                res.push_back(nums1[i]);
                i++;
            }
            else
            {
                res.push_back(nums2[j]);
                j++;
            }
        }
        while(i<nums1.size())
        {
            res.push_back(nums1[i]);
            i++;
        }
        while(j<nums2.size())
        {
            res.push_back(nums2[j]);
            j++;
        }
        return res;
    }
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        vector<int> temp=MergeSort(nums1,nums2);
        double res;
        int len=temp.size();
        if(temp.size()%2==0)
            res=(double)(temp[len/2]+temp[(len/2)-1])/2;
        else
            res=temp[len/2];
        return res;
    }
};


算法2:
class Solution {
public:
    double find_kth(vector<int>& nums1,vector<int>& nums2,int m1,int m2,int k,int begin1,int begin2)
    {
        if(m1 > m2)
            return find_kth(nums2,nums1,m2,m1,k,begin2,begin1);
        if(m1 == 0)
            return nums2[k-1];
        if(k == 1)
            return nums1[begin1] < nums2[begin2]?nums1[begin1]:nums2[begin2];
        int a=min(k/2,m1);  //the ath element in A
        int b=k-a;          //the bth element in B
        if(nums1[begin1+a-1] < nums2[begin2+b-1])  //compare the ath element in A and the bth element in B
            return find_kth(nums1,nums2,m1-a,m2,k-a,begin1+a,begin2);
        else
            return find_kth(nums1,nums2,m1,m2-b,k-b,begin1,begin2+b);
    }
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m1=nums1.size();
        int m2=nums2.size();
        int k=(m1+m2)>>1;
        if((m1+m2)%2==1)
            return find_kth(nums1,nums2,m1,m2,k+1,0,0);
        else
            return (find_kth(nums1,nums2,m1,m2,k+1,0,0)+find_kth(nums1,nums2,m1,m2,k,0,0))/2;
    }
};








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值