力扣算法题 4. 寻找两个正序数组的中位数

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

直接暴力很好做,但是题目有时间复杂度要求,这里不展示

因为时间复杂度中有log,向二分法的方向考虑,求中位数的问题可以变成求两个有序数组中第k小数的问题,具体详解见力扣题解区

#include <iostream>
#include "string"
#include "vector"
#include "list"
#include "unordered_set"

using namespace std;

double Find(vector<int>& nums1, int star1,int end1,vector<int>& nums2,int star2,int end2,int k)
{
    int temp=k/2;

    //求数组1和数组2的长度
    int n=end1-star1;
    int m=end2-star2;

    //边界情况,如果数组1中没有数,返回数组2中第k小数
    if(n==0)
    {
        return nums2[k+star2-1];
    }
    //同上
    else if(m==0)
    {
        return nums1[k-1+star1];
    }

    //如果k为1,取数组1和2中较小数即可
    if(k==1)
    {
        return min(nums1[star1],nums2[star2]);
    }

    //如果数组1的长度小于k/2,则根据数组1的长度选取比较的数
    if(n<=k/2)
    {
        if(nums1[n+star1-1]<nums2[n+star2-1])
        {
            return Find(nums1,end1,end1,nums2,star2,end2,k-n);
        }
        else if(nums1[n+star1-1]>=nums2[n+star2-1])
        {
            return Find(nums1,star1,end1,nums2,star2+n,end2,k-n);
        }
    }
    //同上,数组2
    else if(m<=k/2)
    {
        if(nums1[m+star1-1]<nums2[m+star2-1])
        {
            return Find(nums1,star1+m,end1,nums2,star2,end2,k-m);
        }
        else if(nums1[m+star1-1]>=nums2[m+star2-1])
        {
            return Find(nums1,star1,end1,nums2,end2,end2,k-m);
        }
    }

    if(nums1[k/2+star1-1]<nums2[k/2+star2-1])
    {
        //cout<<"nums1:"<<nums1[k/2+star1-1]<<endl<<"nums2:"<<nums2[k/2+star2-1]<<endl;
        return Find(nums1,star1+k/2,end1,nums2,star2,end2,k-k/2);
    } else
    {
        return Find(nums1,star1,end1,nums2,star2+k/2,end2,k-k/2);
    }

    return 0;
}

double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2)
{
    int sum;
    sum=nums1.size()+nums2.size();
    int k=sum/2+1;
    
//如果数组长度之和为奇数,取最中间的数即可
    if(sum%2!=0)
    {
        return Find(nums1,0,nums1.size(),nums2,0,nums2.size(),k);
    }
    //如果是偶数,取两数之和
    else if(sum%2==0)
    {
        //return (Find(nums1,0,nums1.size(),nums2,0,nums2.size(),k-1)+ Find(nums1,0,nums1.size(),nums2,0,nums2.size(),k))/2;
        double k1= Find(nums1,0,nums1.size(),nums2,0,nums2.size(),k-1);
        double k2=Find(nums1,0,nums1.size(),nums2,0,nums2.size(),k);
        return (k1+k2)/2;
    }


    return 0;
}

//自主测试
int main() {
    vector<int> num1;
    vector<int> num2;

    int sum;
    cin >> sum;
    while (sum != -1) {
        num1.push_back(sum);
        cin >> sum;
    }

    cin >> sum;
    while (sum != -1) {
        num2.push_back(sum);
        cin >> sum;
    }

    double count = findMedianSortedArrays(num1, num2);

    cout << count;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值