由于时间复杂度要求是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;
}