Median of Two Sorted Arrays

来源:互联网 发布:网络高清摄像头安装方法 编辑:程序博客网 时间:2024/05/22 06:18

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

两个有序数组,大小分别为m和n,找出这两个有序数组的中值。算法的时间复杂度应该控制在O(log(m+n))内。

求解算法

    1.普通算法

    刚开始看到题目,想到合并两个数组,然后找出这个有序数组中的中值。但是这种方法的复杂度为O(m+n)>O(log(m+n)),因此,必须寻找其他方法。

      2.递归算法

      两个有序数组的中值,考虑到m+n为奇数或者偶数的原因,就是求两个有序数组中排好序得到的第(m+n)/2个数的值或者是(m+n)/2和(m+n)/2+1的平均值。于是问题便转化为如何求第(m+n)/2个数的值?

      引入两个数组中求第k个值的算法,假设有序数组A和有序数组B大小都大于k/2,并且他们都是非递减排序。我们对A[k/2]和B[k/2]进行比较,情况有三种

      1) A[k/2]==B[k/2],则第k个值即为A[k/2]
      2) A[k/2]>B[k/2],则说明B[k/2]小于A和B组成的有序数组中的第k个数
      3) B[k/2]>A[k/2],则说明A[k/2]小于A和B组成的有序数组中的第k个数

      对于第(1)种情况,显然已经找到了第k个值,无需再求

      对于第(2)种情况,因为A的前k/2个数和B的前k/2个数加起来总共是K个数,我们又已知A[k/2]>B[k/2]。因此B[k/2]的值肯定不是第K个值,它的排序小于K。既然我们知道了B的前k/2个数不可能找到第K个值,于是我们直接排除B的前K/2个数,从数组B的[K/2+1,n]范围和A的[0,m]范围继续寻找第K-K/2个值。(因为我们已经排除了K/2个值,因此以前的K在新的两个数组中排名为第K-K/2),以此类推,我们逐步减少搜索范围,最后确定第k个值。但是实际的情况中每次排除的数据不一定是K/2,因此A或者B的数组中有一个小于K/2,因此要考虑其他情况应对。

      算法步骤(其中m和n分别为数组A和数组B的大小)

      a)求出m+n的和s,如果s为奇数,则第(s+1)/2为 两个有序数组的中值,如果s为偶数,则第(s+1)/2和(s+1)/2+1的平均值为其中值。假设我们求第K个值

      b)比较m和K/2的大小:

      • 如果m<=K/2,设 pa = m,pb = K - pa
      • 如果n<=K/2并且,设pb = n,pa = K-pb
        -否则pa = K/2,pb = K - pa

      c)比较A[pa]和B[pb]的大小,这就进入了我们第K个值得节奏。调用第求解两个有序数组中K个值的算法

      代码:

      class Solution {public://求第k个数的算法double findKthNumber(vector<int>& va,vector<int>& vb,unsigned k){    if (k > va.size() + vb.size())        return 0;    if (va.size() == 0)        return vb.at(k-1);    else if (vb.size() == 0)        return va.at(k - 1);    else if (k == 1)        return va.at(0) < vb.at(0) ? va.at(0) : vb.at(0);           unsigned half_k = k / 2;                    //求出k的一半的值    size_t la,lb;    if (half_k >= va.size())                    //如果va还没有k的一半大    {        la = va.size();        lb = k - la;        }    else if(half_k>=vb.size())                  //如果vb还没有k的一半大    {        lb = vb.size();        la = k - lb;    }    else    {        la = half_k;        lb = k - half_k;    }    if (va.at(la - 1) < vb.at(lb - 1))        //删除va中多余的数    {        int temp = la;        while (0<temp--)            va.erase(va.begin());                   return findKthNumber(va, vb, k - la);    }    else if (va.at(la - 1) == vb.at(lb - 1))  //删除vb中多余的数        return va.at(la - 1);    else    {        int temp = lb;        while (0 < temp--)            vb.erase(vb.begin());        return findKthNumber(va, vb, k - lb);    }}    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {        size_t ttl_len = nums1.size() + nums2.size();    if (ttl_len % 2 != 0)        return findKthNumber(nums1, nums2, ttl_len / 2 + 1);    vector<int> v1(nums1);    vector<int> v2(nums2);    double median1 = findKthNumber(nums1, nums2, ttl_len / 2 );    double median2 = findKthNumber(v1, v2, ttl_len / 2 + 1);    return (median1 + median2) / 2;    }};
      1 0