已知有两个等长的非降序序列S1, S2, 设计函数求S1与S2并集的中位数。有序序列A0,A1,⋯,AN−1的中位数指A(N−1)/2的值,即第⌊(N+1)/2⌋个数(A0为第1个数)。
输入格式:
输入分三行。第一行给出序列的公共长度N(0<N≤100000),随后每行输入一个序列的信息,即N个非降序排列的整数。数字用空格间隔。
输出格式:
在一行中输出两个输入序列的并集序列的中位数。
输入样例1:
5
1 3 5 7 9
2 3 4 5 6
输出样例1:
4
输入样例2:
6
-100 -10 1 1 1 1
-50 0 2 3 4 5
输出样例2:
1
题目大意:求两个组数的中位数,并要求时间复杂度为O(logN)
解题思路:二分+递归
既然时间复杂度是O(logN),那么一看就知道用二分法,在两组数a,b中各取中位数ma,mb,比较大小。
数组长度为n —> 中位数为第n个 —>数组必有n-1个数比中位数小
若a[ma]==b[mb] —> 第n个数和第n+1个数都是a[ma] —> 中位数为a[ma]
若a[ma]<b[mb] —> 中位数在a[ma]的右边,b[mb]的左边(一定要有n-1个数比中位数小)
若a[ma]>b[mb] —> 中位数在a[ma]的左边,b[mb]的右边(同上)
最后剩余的判断范围的奇偶会影响下一次递归的参数,需判断
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n; 4 const int maxn=1e5+5; 5 int a[maxn],b[maxn]; 6 int binary(int la,int ra,int lb,int rb){ 7 if(la>=ra||lb>=rb) return a[la]>b[lb]?b[lb]:a[la]; 8 int ma=(la+ra)>>1,mb=(lb+rb)>>1; 9 if(a[ma]==b[mb]) return a[ma]; 10 else if(a[ma]<b[mb]){ 11 if((ra-la+1)&1) return binary(ma,ra,lb,mb); 12 else return binary(ma+1,ra,lb,mb); 13 }else{ 14 if((rb-lb+1)&1) return binary(la,ma,mb,rb); 15 else return binary(la,ma,mb+1,rb); 16 } 17 } 18 int main(){ 19 cin>>n; 20 for(int i=0;i<n;i++) cin>>a[i]; 21 for(int i=0;i<n;i++) cin>>b[i]; 22 cout<<binary(0,n-1,0,n-1)<<'\n'; 23 return 0; 24 }View Code
复杂度分析:空间复杂度没什么好说的就两个长度为n的数组,且n最大值为1e5。
时间复杂度则因为采取了二分法所以为O(logN)
心得体会:加强了对二分法的灵活运用,更加熟练掌握二分法。