二分查找&&二分中位数

Posted qq2210446939

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分查找&&二分中位数相关的知识,希望对你有一定的参考价值。

普通二分查找

 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 
View Code

 

至此我们可以写出这样的代码,还缺了点边界情况和终止条件。

那么极端情况是什么呢,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 
View Code

 输入的复杂度为O(n),查找的复杂的为O(logn),总复杂度为O(logn)  (手动滑稽)。

 

 

    

 

以上是关于二分查找&&二分中位数的主要内容,如果未能解决你的问题,请参考以下文章

leetcode 二分查找&指针解题

二分查找&二分答案

hiho36 二分·二分查找二分查找

二分查找&好久不见

LC T668笔记 & 有关二分查找第K小数BFPRT算法

C语言顺序查找&二分查找