leetcode 0004 寻找两个正序数组的中位数 - hard

1 题目:寻找两个正序数组的中位数

给定两个大小分别为 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

提示:

n u m s 1. l e n g t h = = m nums1.length == m nums1.length==m
n u m s 2. l e n g t h = = n nums2.length == n nums2.length==n
0 < = m < = 1000 0 <= m <= 1000 0<=m<=1000
0 < = n < = 1000 0 <= n <= 1000 0<=n<=1000
1 < = m + n < = 2000 1 <= m + n <= 2000 1<=m+n<=2000
− 1 0 6 < = n u m s 1 [ i ] , n u m s 2 [ i ] < = 1 0 6 -10^6 <= nums1[i], nums2[i] <= 10^6 106<=nums1[i],nums2[i]<=106

2 暴力破解

数据量不大,可以直接合并数组,然后求中位数。

double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
    vector<int> nums3;
    int i = 0, j = 0;
    while (i < nums1.size() && j < nums2.size()){
        if(nums1[i] < nums2[j])
            nums3.push_back(nums1[i++]);
        else
            nums3.push_back(nums2[j++]);
    }

    while (i < nums1.size()){
        nums3.push_back(nums1[i++]);
    }

    while (j < nums2.size()){
        nums3.push_back(nums2[j++]);
    }
    return (nums3[(nums3.size() - 1)/ 2] + nums3[nums3.size() / 2]) / 2.0;
}
结果

leetcode 0004 寻找两个正序数组的中位数 - hard_第1张图片

3 不合并数组,直接在原数组中查找

将中位数求解转换为求第k小的数,然后分奇偶讨论。

int findKthElement(vector<int>& nums1, vector<int>& nums2, int k){
    int i = 0, j = 0;

    while (i < nums1.size() && j < nums2.size()){
        if(i + j + 1 == k){
            return min(nums1[i], nums2[j]);
        }
        if(nums1[i] < nums2[j]) {
            i++;
        }else {
            j++;
        }
    }

    if(i < nums1.size()){
        return nums1[k - nums2.size() - 1];
    }else{
        return nums2[k - nums1.size() - 1];
    }
}

double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
    int n = nums1.size() + nums2.size();
    int a =  findKthElement(nums1, nums2, (n + 1) / 2);
    if(n % 2 == 1){
        return a;
    }
    return (findKthElement(nums1, nums2, n / 2 + 1) + a) / 2.0;
}
结果

leetcode 0004 寻找两个正序数组的中位数 - hard_第2张图片

4 优化时间复杂度满足O(log(m+n))

每次排除 k / 2 个数,指导一个数组为空,或者 k = 1

int findKthElement(vector<int>& nums1, vector<int>& nums2, int k){
    int n = nums1.size(), m = nums2.size();
    int offset1 = 0;
    int offset2 = 0;

    while (1){
        if(offset1 == n) return nums2[offset2 + k - 1];
        if(offset2 == m) return nums1[offset1 + k - 1];
        
        if(k == 1) return min(nums1[offset1], nums2[offset2]);
        int x = k / 2 - 1;
        int newoffset1 = min(n - 1, offset1 + x);
        int newoffset2 = min(m - 1, offset2 + x);
        if(nums1[newoffset1] < nums2[newoffset2]){
            k -= newoffset1 + 1 - offset1;
            offset1 = newoffset1 + 1;
        }else{
            k -= newoffset2 + 1 - offset2;
            offset2 = newoffset2 + 1;
        };
    }
}

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