普通二分查找
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 }
至此我们可以写出这样的代码,还缺了点边界情况和终止条件。
那么极端情况是什么呢,ab序列都只有一个的时候,最终答案自然是小的那个,
那么跑一遍样例,看看有没有错,发现了死循环:
当a序列为3 5 ,b序列为4 时,ma=3,mb=4,ma的左边和mb的右边删无可删了,所以这算一种边界情况。
推广,当总序列只有三个元素时,算一种边界情况,那么最终答案肯定是三个数中间那个数,我的做法:出现两序列不等长的时候,让小的那个序列左指针右移一就行,然后就会回到第一种终止条件!
代码:
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 9 if(la==ra){ 10 return a[ma]<b[mb]?a[ma]:b[mb]; 11 } 12 if(a[ma]==b[mb]){ 13 return a[ma]; 14 } 15 if(a[ma]<b[mb]){ 16 la=ma; 17 rb=mb; 18 if(ra-la!=rb-lb) 19 ra-la > rb-lb ? la++ :lb++; 20 bs(la,ra,lb,rb); 21 } 22 else if(a[ma]>b[mb]){ 23 lb=mb; 24 ra=ma; 25 if(ra-la!=rb-lb) 26 ra-la > rb-lb ? la++ :lb++; 27 bs(la,ra,lb,rb); 28 } 29 } 30 int main() 31 { 32 cin>>n; 33 for(int i=1;i<=n;i++) 34 cin>>a[i]; 35 for(int i=1;i<=n;i++) 36 cin>>b[i]; 37 cout<<bs(1,n,1,n); 38 return 0; 39 }
输入的复杂度为O(n),查找的复杂的为O(logn),总复杂度为O(logn) (手动滑稽)。
原文地址:https://www.cnblogs.com/qq2210446939/p/11571934.html
时间: 2024-10-08 09:05:53