代码题(44)— 两个排序数组的中位数

1、4. 两个排序数组的中位数

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 。

请找出这两个有序数组的中位数。要求算法的时间复杂度为 O(log (m+n)) 。

你可以假设 nums1 和 nums2 均不为空。

示例 1:

nums1 = [1, 3]
nums2 = [2]

中位数是 2.0

示例 2:

nums1 = [1, 2]
nums2 = [3, 4]

中位数是 (2 + 3)/2 = 2.5

  这道题让我们求两个有序数组的中位数,而且限制了时间复杂度为O(log (m+n)),看到这个时间复杂度,自然而然的想到了应该使用二分查找法来求解。但是这道题被定义为Hard也是有其原因的,难就难在要在两个未合并的有序数组之间使用二分法,这里我们需要定义一个函数来找到第K个元素,由于两个数组长度之和的奇偶不确定,因此需要分情况来讨论,

  对于奇数的情况,直接找到最中间的数即可,偶数的话需要求最中间两个数的平均值。

  下面重点来看如何实现找到第K个元素,首先我们需要让数组1的长度小于或等于数组2的长度,那么我们只需判断如果数组1的长度大于数组2的长度的话,交换两个数组即可,然后我们要判断小的数组是否为空,为空的话,直接在另一个数组找第K个即可。还有一种情况是当K = 1时,表示我们要找第一个元素,只要比较两个数组的第一个元素,返回较小的那个即可。

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int total = nums1.size() + nums2.size();
        if(total%2 == 1)
            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;
    }
    double findKth(vector<int>& nums1,int i, vector<int>& nums2, int j, int k)
    {
        // 首先需要让数组1的长度小于或等于数组2的长度,不满足则交换两个数组
        if((nums1.size()-i) > (nums2.size()-j))
            return findKth(nums2,j,nums1,i,k);
        // 判断小的数组是否为空,为空的话,直接在另一个数组找第K个即可
        if(nums1.size() == i)
            return nums2[j+k-1];
        // 当K = 1时,表示我们要找第一个元素,只要比较两个数组的第一个元素,返回较小的那个即可
        if(k==1)
            return min(nums1[i], nums2[j]);
        
        //记录两组中位数下标
        int pa = min(i+k/2, int(nums1.size()));
        int pb = j+k-pa+i;
        
        if (nums1[pa - 1] < nums2[pb - 1]) {
            return findKth(nums1, pa, nums2, j, k - pa + i);//
        }
        else if (nums1[pa - 1] > nums2[pb - 1]) {
            return findKth(nums1, i, nums2, pb, k - pb + j);
        }
        else {
            return nums1[pa - 1];
        }
        
    }
};
原文地址:https://www.cnblogs.com/eilearn/p/9454099.html