无处不在的二分查找
来源:互联网 发布:win8无法连接到此网络 编辑:程序博客网 时间:2024/04/27 17:07
引入
什么是二分查找?
先来一个简单的游戏,我选定了1-100之间的某个数,你来猜。50?太大了。25?太小了。如此,游戏进行下去,直到你猜中为止。这样,对区间为1-n之间的整数,你可以在log(n)次之内猜中。
在某一给定范围内,查找某个对象,每次查找可以判断该对象与相应位置值的关系。二分查找通过查找当前范围的中间位置来定位,这样每次查找之后,查找的范围都会变为原来的一半。二分查找其实是一种分而治之的思想,将查找的任务分解为两个子空间,每次比较都判断下一个查询的子空间,依次迭代之后,最终达到查询的目的。
性能
对比用顺序查找的方法,如从1开始往n逐个猜测,平均需猜测n/2次。
如果n为100万,使用二分查找,只需20次,而顺序查找平均需100万次,可以看出二分查找的强大性能。
关于这种方法快速的实质,在《数学之美番外篇》中,有很生动的探讨,基本idea是,每次查找得到的分支,都是等概率的。
用处
二分查找应用范围很广,最常见的当然是有序数组中的元素查找。数学上,求解方程的近似解时,也会用到二分法查找。
在《编程珠玑》”2、9章都有提及。而《编程之美》3.11节“程序改错”中,提到的第一个改错就是二分查找。
用法
1.最简单的查找是在有序数组中,查找某个数,返回任意一个满足的索引。
如数组1,5,19,20,31,31,401 中查找31,满足的有2个,则查找返回任意一个位置都可以。
算法设计很简单,使用三个标记:l,u,m; l代表当前搜索的范围的下界,u代表上届,m为l和u的中值(向下取整)。
迭代过程只需比较m位置的值与x(所查找的值)关系,若 a[m]>x,则x只可能出现在左边的区间,此时只需修改u为m-1;若a[m]<x,则x只可能出现在右边的区间,此时只需修改l的值为m+1;迭代终止条件为l值大于u。
int bisearch_v1(int*a,int n,int x){int l=0,u=n-1,m;while (l<=u){m=l+(u-l)/2;//注意 没有使用m=(l+u)/2;防止越界if(a[m]==x) return m;if (a[m]>x)u=m-1;elsel=m+1;}return -1;}
2.上述算法有两个问题:
a.每次循环迭代,需要比较两次,有没有更高效的算法?
b. 有多个符号条件的位置时,不能返回特定位置要求。
重新定义问题:在有序数组中,查找某个数,返回一个满足的索引,如有多个位置满足要求,则返回第一个满足的索引。
关键思路: 仍然使用三个标记:l,u,m。设有关系式:a[l]<x<=a[u],并假设 a[-1]<x,a[n]>=x。其中l 代表检索范围内,已检索的小于x的最大索引,初始值为-1;u代表检索范围内,已检索的大于或等于x的最小索引。迭代终止条件为l+1==u,此时l 指向的是有序数组中,小于x的最大索引,而u为大于或等于x的最小索引。只需检测u,a[u]与x的关系即可。
int bisearch_v2(int *a,int n,int x){//注意对比1中 l,u的初始值,迭代终止条件,以及l,u的修改方法int l=-1,u=n,m;while (l+1!=u){m=l+(u-l)/2;if (a[m]<x)l=m;elseu=m;}if(u!=n&&a[u]==x)return u;elsereturn -1;}
3.类似2中描述,如《编程之美》所提出的 ,找出一个有序(字典序)字符串数组中,值等于字符串v的元素的序号,如果有多个元素满足这个条件,则返回其中最大的序号。
可用2中分析的方法来解。
同时该书中提到多个二分查找类似的问题,摘录如下:
a.给定一个有序(不降序)数组arr,求任意一个i使得arr[i] 等于v,不存在则返回-1
b.给定一个有序(不降序)数组arr,求最小的i使得arr[i] 等于v,不存在则返回-1
c.给定一个有序(不降序)数组arr,求最大的i使得arr[i] 等于v,不存在则返回-1
d.给定一个有序(不降序)数组arr,求最大的i使得arr[i] 小于v,不存在则返回-1
e.给定一个有序(不降序)数组arr,求最小的i使得arr[i] 大于v,不存在则返回-1
有兴趣的朋友可以思考下。
- 无处不在的二分查找
- 无处不在的二分查找
- 无处不在的二分查找
- 无处不在的二分搜索
- 浅谈:无处不在的二分(1)
- 浅谈:无处不在的二分(2)
- 二分查找和递归的二分查找
- 二分查找的思考
- 二分查找的总结
- vector的二分查找
- 二分查找的应用
- 二分查找的扩展
- 改进的二分查找
- 简单的二分查找
- 二分查找的扩展
- 二分查找的感悟
- 二分查找的实现
- 二分查找的技巧
- 关于单例
- 主窗体最小化时不显示在任务栏
- 万恶写完的都没了
- Oracle Database 12c 行限制子句
- 数据结构与算法他人小实用汇总 【汇总】
- 无处不在的二分查找
- Unity:图片翻动浏览效果Demo
- 升采样(Upsampling)技术
- 输入一个整数字符串,将该字符串转换成整数并输出
- Baidu 问到 红黑树 【面】
- 快速排序之我见
- Baidu 手写中序遍历二叉树非递归 和 链栈 【面】
- 结构体字节对齐
- 旧工程适配iOS6和iPhone5续之第三方静态库