Leetcode4.寻找两个正序数组的中位数C++

题目

给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。

算法的时间复杂度应该为 O(log (m+n)) 。

示例 1:

输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
示例 2:

输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5

提示:

nums1.length == m
nums2.length == n
0 <= m <= 1000
0 <= n <= 1000
1 <= m + n <= 2000
-106 <= nums1[i], nums2[i] <= 106
通过次数829,238提交次数1,995,256

思想

这题有两种思路,1递归,2二分,二分有点难以理解,这里递归是最简单的解法。

把找两个数组的中位数转换为找第k个数。要查找的k即为总长度的一半(中位数)

首先每次都分别取出两个数组的中位数(k/2)

有三种情况

1. nums1[k/2] > nums2[k/2]

此时nums2数组中的前k/2个数不可能是第k个数,可以直接删除,接下去遍历时寻找第nums2中k - k / 2和nums1中的全部即可

2. nums1[k/2] < nums2[k/2] 刚好相反

3.nums1[k/2] = nums2[k/2],此时任意输出一个就可

代码

class Solution {
public:
    double findMedianSortedArrays(vector& nums1, vector& nums2) {
        int total = nums1.size() + nums2.size();
        if(total % 2) return find(nums1, 0, nums2, 0, total / 2 + 1);//奇数直接返回中间值
        else {//偶数返回两数的平均数
            int left = find(nums1, 0, nums2, 0, total / 2);
            int right = find(nums1, 0, nums2, 0, total / 2 + 1);
            return (left + right) / 2.0;
        }
    }
    //k从1开始
    int find(vector& nums1, int i, vector& nums2, int j, int k)
    {
        //假定nums1的长度较小,方便code
        if(nums1.size() - i > nums2.size() - j) return find(nums2, j, nums1, i, k);

        //若nums1长度为0,则直接返回第二个数组中的第k个元素
        if(nums1.size() == i) return nums2[j + k - 1];

        //如果k=1,返回两个数头部较小的元素
        if(k == 1) return min(nums1[i], nums2[j]);

        //三种情况
        int si = min((int)nums1.size() - 1, i + k / 2 - 1), sj = j + k - k / 2 - 1;//两个数组分别的中点
        if(nums1[si] > nums2[sj])
            return find(nums1, i, nums2, sj + 1, k - (sj - j + 1));
        else 
            return find(nums1, si + 1, nums2, j, k - (si - i + 1));
    }
};

你可能感兴趣的:(leetcode,leetcode,算法,职场和发展)