Median of Two Sorted Arrays

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 (0return 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;
          }
      };

      你可能感兴趣的:(c++,LeetCode)