• 4. Median of Two Sorted Arrays[H]两个有序数组的中位数


    题目

    There are two sorted arrays nums1 and nums2 of size m and n respectively.
    Find the midian of the two sorted arrays. The overall run time complexity should be O(log(m+n)).
    You may assume nums1 and nums2 cannot be both empty.
    Example1:
      nums1 = [1, 3]
      nums2 = [2]
      The median is 2.0
    Example2:
      nums1 = [1, 2]
      nums2 = [3, 4]
      The median is (2+3)/2.0 = 2.5

    思路


    二分查找、递归法

    假设两个数组A和B中的个数都大于(frac{k}{2})个(存在某一数组个数不足(frac{k}{2})个),分别取出第(frac{k}{2})个元素(数组下标为$frac{k}{2}-$1)进行比较,此时有三种情况:

    • A[$frac{k}{2}-$1] (;)< (;) B[$frac{k}{2}-$1]
    • A[$frac{k}{2}-$1] (;)=(;) B[$frac{k}{2}-$1]
    • A[$frac{k}{2}-$1] (;)>(;) B[$frac{k}{2}-$1]

    对于第一种情况,如果A的第 (frac{k}{2}) 个元素(数组下标为 $ frac{k}{2}-1$ )比B的第 (frac{k}{2}) 个元素(数组下标为 (frac{k}{2}-1) )小,说明当A和B合并之后,A的下标从0到( (frac{k}{2}-1) )之间的数都不可能是第k大的数,即对数组cut的小了,应该增大k。如果相等,就是需要寻找的元素(第k-1个元素)。大于的情况与小于类似。奇数个就取中间的,偶数个将两个数加起来除以2.0即可。
    递归的边界条件:
    1)其中某一数组为空的话,则直接返回另一个数组下标为[k-1]的数。(见单数组寻找第k个元素)
    2)如果k=1,即查找最小值,直接比较两个数组的第1个元素(数组下标为0)即可。
    3)如果A[$frac{k}{2}-(1]=B[)frac{k}{2}-$1],只需要返回其中的一个。

    Tips


    Cut思想寻找第k个数

    通过Cut,将数组切割为左右两部分:(Left_{part}, Right_{part}),此时产生两个元素,分别是左边的最大值(L_{max})和右边的最小值(R_{min})。Cut过程中,可以Cut一个数,则这个数既属于左边,又属于右边;也可以在两个数中间Cut。

    • 单数组寻找第k个元素
      对于有序数组A,在第k个数(数组下标为k-1)cut一下,返回值(A[k-1]=L{max}),即为第k个数,该数为左边部分最大值。(k=1,2,...)

    • 双数组寻找第k个元素

    (left_{part}) (C_i) $right_{part} $
    (a_1,a_2,cdots,a_i) / (a_{i+1},a_{i+2},cdots,a_m)
    (b_1,b_2,cdots,b_j) / (b_{j+1},b_{j+2},cdots,a_n)

    定义(L_{max_1}),(L_{max_2})为Cut之后(Left_part)第1个和第2个数组的最大值,(R_{min_1}),(R_{min_2})为Cut之后(Right_{part})第1个和第2个数组的最小值。(C_1、C_2)是第1、2个数组的Cut。
    如果满足:
    1)(L_{max_1};< ;R{min_1})(L_{max_2} ; <; R_{min_2})。(这是一定满足的,因为数组有序,左边一定小于右边。)
    2)(L_{max_1};<=;R_{min_2}),且(L_{max_2};<=;R_{min_1})
    (Left_{part})全小于(Right_{part})如果左边的元素个数加起来刚好等于k,那么第k个元素就是(Max(L_{max_1},L_{max_2}))(参见单数组寻找第k个元素)。如果(L_{max_1};>;R_{min_2}),说明数组1的左边元素太多(大)了,需要减小(C_1),把(C_2)增大。同理可得(L_{max_2};>;R_{min_1}),将(C_1)增大,(C_2)减小。

    C++

    class Solution {
    public:
         double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
             
             int n1 = nums1.size();
             int n2 = nums2.size();    
             int total = n1 + n2;
             
             if(total % 2){ //如果数组加起来是奇数 
                 return findKth(nums1, 0, nums2, 0, total / 2 + 1);
             }
             else{ //如果是偶数
                 return (findKth(nums1, 0, nums2, 0, total / 2 ) + findKth(nums1, 0, nums2, 0, total / 2 + 1) )/2.0;
             }
               
         }
        
        //分割的思想寻找第k个数
        double findKth(vector<int>& nums1, int l, vector<int>& nums2, int r, int k){
            
            int n1 = nums1.size();
            int n2 = nums2.size();
            
            if(n1 - l > n2 -r ) 
                  return findKth(nums2, r, nums1, l, k); //始终保证第一个数组是个数是最少的
            
            if(n1-l == 0)
                return nums2[r + k -1];
            if(k == 1)
                return min(nums1[l], nums2[r]);
            
            int p1 = min(k/2 , n1); //保证在第一个数组内做二分查找。
            int p2 = k - p1;
            
            if(nums1[l + p1 -1] < nums2[r + p2 -1]){ //左边
                return findKth(nums1, l+p1,nums2, r,k - p1);
            }
            else if(nums1[l + p1 -1] > nums2[r + p2 -1]){ //左边数组1的个数太大
                return findKth(nums1, l,nums2, r+p2,k - p2);
            }
            else{
                return nums1[l+p1-1];
            }
        }  
    };
    

    python

    class Solution(object):
        def findKth(self, nums1, nums2,k):
            
            k = int(k)
            n1 = len(nums1)
            n2 = len(nums2)
            
            if n1 > n2: 
                return self.findKth(nums2, nums1, k)
            if n1 == 0: 
                return nums2[k - 1]
            if k == 1: 
                return min(nums1[0], nums2[0])
            p1 = int(min(k / 2, n1))
            p2 = k - p1
            if nums1[p1 - 1] <= nums2[p2 - 1]:
                return self.findKth(nums1[p1:], nums2, p2)
            else:
                return self.findKth(nums1, nums2[p2:], p1)
            
        def findMedianSortedArrays(self, nums1, nums2):
            """
            :type nums1: List[int]
            :type nums2: List[int]
            :rtype: float
            """
            n1 = len(nums1)
            n2 = len(nums2)
            total = n1 + n2
            if(total % 2):
                return self.findKth(nums1, nums2, total /2 + 1)
            else:
                return (self.findKth(nums1, nums2, total /2 )+ self.findKth(nums1, nums2, total /2 + 1))/2.0           
    

    参考

    [1] https://blog.csdn.net/hk2291976/article/details/51107778
    [2] https://leetcode.com/problems/median-of-two-sorted-arrays/solution/

  • 相关阅读:
    Activity与Fragment间的通信
    Activity生命周期.lanchMode.保存状态
    网络知识
    Android内存优化(使用SparseArray和ArrayMap代替HashMap)
    进程/线程死锁产生的原因以及如何避免死锁
    Android UI框架基本概念
    android在线源码
    y音频学习
    给 Android 开发者的 RxJava 详解
    设计模式之观察者模式
  • 原文地址:https://www.cnblogs.com/Jessey-Ge/p/10991587.html
Copyright © 2020-2023  润新知