普通二分查找
1 int bs(int L,int R,int x) 2 {//在l到r区间上查找x,找不到就返回-1 3 int l=L,r=R; 4 while(l<=r){ 5 int m=l+r>>1; 6 if(a[m]==x){ 7 return m; 8 } 9 else if(a[m]>x){ 10 r=m-1; 11 } 12 else{ 13 l=m+1; 14 } 15 } 16 return -1; 17 }
普通版很简单就不详细总结了
二分查找中位数
题意:给定长度为n的两个有序序列,求两个序列合并后的中位数
直接归并法,找到第(2n+1)/2数时停止并输出答案,复杂度为O(n)
但题目要求logn,我们就得换个思路了;
题目给的是两个有序序列,所以两个序列的中位数都可以O(1)求得,那么最终答案的中位数和这两个序列的中位数有什么关系呢?假设第一个序列叫a,中位数为ma,第二个是b,中位数为mb,他们的并集是c,最终答案为ans。
如果ma==mb,也就是说,ma的两端和mb的两端分别在ans的两端,ans也就是ma+mb>>1,也就是随便一个了
如果ma<mb,也就是说,a的中位数比b的要小,所以a的左边和b的右边可以不用考虑了,ans一定在ma与mb中间
如果ma>mb,情况同上,把b视作a,a视作b即可
那么每一次都可以删掉c的一半,直到达到终止条件(假装知到),复杂度就是O(logn)了!
1 #include<iostream> 2 using namespace std; 3 int a[100010],b[100010]; 4 int n; 5 int bs(int la,int ra,int lb,int rb){ 6 int ma=la+ra>>1; 7 int mb=lb+rb>>1; 8 if(a[ma]==b[mb]){ 9 return a[ma]; 10 } 11 if(a[ma]<b[mb]){ 12 bs(la,ra,lb,rb); 13 } 14 else if(a[ma]>b[mb]){ 15 bs(la,ra,lb,rb); 16 } 17 } 18 int main() 19 { 20 cin>>n; 21 for(int i=1;i<=n;i++) 22 cin>>a[i]; 23 for(int i=1;i<=n;i++) 24 cin>>b[i]; 25 cout<<bs(1,n,1,n); 26 }