二分查找&&二分中位数

普通二分查找

 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

二分查找&&二分中位数的相关文章

二分查找&amp;二分答案

原创建时间:2018-02-06 16:48:20 \(O(\log_2n)\)的优秀算法 二分查找 百度百科原话 二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法.但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列. 二分查找的时间复杂度是\(O(log_{2}n)\) 要求 查找的序列必须采用顺序存储结构 查找的序列必须是有序排列的 思路 将需要查找的序列进行排序(一般为升序排列) 将序列中间位置记录的元素与关键字比较 如果相等,则返回查

python函数:递归函数及二分查找算法

本文和大家分享的主要是python的递归函数及二分查找算法相关内容,一起来看看吧,希望对大家学习python有所帮助. 一.递归的定义 def story(): s = """ 从前有个山,山里有座庙,庙里老和尚讲故事, 讲的什么呢? """ print(s) story() story() 老和尚讲故事 递归的定义 -- 在一个函数里再调用这个函数本身.这种魔性的使用函数的方式就叫做 递归 . 递归的最大深度:997 1.python递归最大层

【Java_Base】常用查找算法:顺序查找、二分查找

顺序查找 从第一个元素开始顺序比较查找. 二分查找 二分查找前提条件: 已排序的数组中查找 二分查找的基本思想是: 首先确定该查找区间的中间点位置: int mid = (low+upper) / 2; 然后将待查找的值与中间点位置的值比较: 若相等,则查找成功并返回此位置. 若中间点位置值大于待查值,则新的查找区间是中间点位置的左边区域. 若中间点位置值小于待查值,则新的查找区间是中间点位置的右边区域. 下一次查找是针对新的查找区间进行的. 1 public class Search{ 2 p

Java数组二分查找

二分查找法一般指二分查找 二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好:其缺点是要求待查表为有序表,且插入删除困难.因此,折半查找方法适用于不经常变动而查找频繁的有序列表.首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功:否则利用中间位置记录将表分成前.后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表.重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找

查询资料:二分查找法

二分查找 编辑 同义词 二分查找法一般指二分查找 二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好:其缺点是要求待查表为有序表,且插入删除困难.因此,折半查找方法适用于不经常变动而查找频繁的有序列表.首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功:否则利用中间位置记录将表分成前.后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表.重复以上过程,直到找到满足条件的记录,使查找成功,或直到

查找 —— 二分查找[递归+非递归]

二分查找 二分查找是对一组有序序列进行查找.根据要查找的k和序列中间元素比较,动态的移动查找范围.以对折的方式缩小查找范围. 递归方式: def binarySearch(A,left,right,k): if left<= right: mid =(left+right)//2 if A[mid] == k: return mid if A[mid]>k: return binarySearch(A,left,mid-1,k) #此处要返回函数运行结果而不是仅仅调用函数 else: retu

二分查找实现

二分查找 二分查找的前提是数组必须有序.这个算法据某本说,百分之九十的都会写错.编写程序需要注意的是 非法输入 尽量使用迭代,因为如果数组很大的话,递归有可能是栈溢出 循环判断条件 注意mid的求值方法,mid = ((right - left) >> 1) + left ;可以防止两个整型值相加时溢出.并注意>>运算符优先级低于+ - * / %,所以要对左移右移加括号.如果没有加括号,得出的答案是错误的.比如:2 >> 1 + 2 你试下打印出来是多少. 数组里的数

#转 二分查找

二分查找 二分查找算法基本思想 二分查找算法的前置条件是,一个已经排序好的序列(在本篇文章中为了说明问题的方便,假设这个序列是升序排列的),这样在查找所要查找的元素时,首先与序列中间的元素进行比较,如果大于这个元素,就在当前序列的后半部分继续查找,如果小于这个元素,就在当前序列的前半部分继续查找,直到找到相同的元素,或者所查找的序列范围为空为止. 用伪代码来表示, 二分查找算法大致是这个样子的: 1 left = 0, right = n -1 2 3 while (left <= right)

【leetcode边做边学】二分查找应用

更多请关注我的HEXO博客:http://jasonding1354.github.io/ 简书主页:http://www.jianshu.com/users/2bd9b48f6ea8/latest_articles 二分查找 二分查找算法是一种在有序数组中查找某一特定元素的搜索算法.搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束:如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较.如果在某一步骤数组 为