前言
目前正在学算法基础,由于需要二分查找,同时又记不住怎么写(理解不深透),于是写下这篇文章
如有错误,望各位指点纠正。 OvO
一、二分查找主体
二分查找函数模板:
int found(int l, int r,int v) { while (l < r) { int m=(l+r)/2; if (a[m]>v) r = m; else if (a[m]<v)l = m + 1; else return m; } return -1;}
二、 二分查找解析
1、过程动态分析
实例:通过二分查找,找到 v 在数组中的对应值 (v=34)
初始状态: l(左边界) 、r(右边界)位于开头和末尾处,m(中值) 位于数组中间。
第一次查找: 首先对比发现 v 小于 m,可得出数组对应值应在其左侧,然后将前中值设为 r (右边界),使得范围发生变化,从而缩小了查找的区间。
第二次查找: v 仍然小于 m,将前中值设为 r ,再一次缩小区间。
第三次查找: v 大于m, 可得出数组对应值应在其右侧,将前中值往右一位设为 l。
在第三次查找后,m 与 l 重合(因为(l+r)/2会舍弃小数部分,得到的也就是l), 对比可得 v 大于 m,则 l 变为 m+1,也就是 l 与 r 相等,因此退出循环,函数 return -1
2、解析二分模板
while (l < r) 找不到时跳出循环
int m=(l+r)/2; 设立中值(用于判断位置)
if (a[m]>v) r = m; 更改右边界
else if (a[m]<v)l = m + 1; 更改左边界
else return m; 找到后直接返回函数
return -1; 说明数组中不含其对应值
更改左边界时为何要加1?
假设对应值位于 [ m , r ] 之间,如上图所示,改变左边界, l 与 m 重合
首先之前可知 ( l + r )/2为 l,也就是 m 不变。
因为v 仍然大于 m,所以改变 l。l 改变后为 m,导致查找后重复不变,并且过程中 l 始终小于 r ,因而进入死循环。
总结
二分查找精髓在于通过缩小区间方法进行查找,更改左右边界要符合条件,防止进入死循环,同时左右边界可以为其他条件,进行不同问题的二分查找