LeetCode - 两个排序数组的中位数(二分)

LeetCode - 两个排序数组的中位数

由于时间复杂度要求是O(log(n+m)),所以合并数组不可取

考虑二分

二分中位数是第一个数组的第几个,然后判断是否满足中位数的条件

也可能中位数在第二个数组,所以只要将第一第二个数组交换后再求一遍即可

当 n+m 为奇数,中位数是数组中的数,在合并后的数组中其左边右边均有(n+m)/2个数(向下取整)

若为偶数,中位数有两个,抛去这两个,左右各有(n+m)/2-1个数

为了方便计算,求有 (n+m)/2 个小于等于num1[x] 的数 x

然后就是判断是否满足条件 

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;
/
int check(int n,int m, int k, vector<int>& nums1, vector<int>& nums2, int mid) { // mid 为数组1贡献的左边元素的数量
    if(mid > k) return 1; // 多了
    if(mid == k && (m ==0 || nums2[0] >= nums1[mid])) return 2; // 满足条件
    if(k - mid - 1 < m && nums2[k-mid-1] > nums1[mid]) return 0;// 数组2能贡献的使总的贡献 < k
    if(k - mid < m && nums2[k-mid] < nums1[mid]) return 1;// 数组2能贡献的使总的贡献 > k
    if(k - mid - 1 >= m) return 0; // 数组2能贡献的使总的贡献 < k
    return 2; // 满足条件
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
    int n = nums1.size(), m = nums2.size();
    int k = (n+m) / 2;
    int l = 0, r = n-1, mid;
    while(l<=r) {
        mid = (l+r) >> 1;
        int ck = check(n, m, k, nums1, nums2, mid);
        if(ck == 1) r = mid - 1; // 多了
        else l = mid + 1; // 少了
        if(ck == 2) break; // 正好
    }
    l --;
    if(l>=0 && check(n, m, k, nums1, nums2, l) == 2) {
        if((n+m) & 1) return nums1[l];
        else {
            int tem = nums1[l] + 1;
            if(l-1>=0) tem = nums1[l-1];
            if(tem == nums1[l] + 1) tem = nums2[k-l-1];
            else if(k-l-1>=0) tem = max(tem, nums2[k-l-1]);
            return 1.0 * (nums1[l] + tem) / 2;
        }
    }
    else return findMedianSortedArrays(nums2, nums1);
}
/ 此区域内为答案
int main()
{
    int n, m, x; vector<int>a, b;
    cin>>n>>m;
    while(n--) scanf("%d", &x), a.push_back(x);
    while(m--) scanf("%d", &x); b.push_back(x);
    cout<<findMedianSortedArrays(a, b)<<endl;
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值