引用请注明出处:http://blog.csdn.net/int64ago/article/details/7425727

看到这个标题无论你是处于怎样的心理进来看了,我觉得都是值得的。因为这个问题太简单,任何一个开始接触“真正”算法基本都是从二分查找开始的。至于二分查找都不知道是什么的可以先去找别的资料看下,再来看这篇文章。既然很简单,那么我们开始一起写一个吧,要求是对num[]={1,2,2,4,4,8,10}不减序列在区间[0,7)进行查找,当然我们得首先保证要查找的数e满足:num[0] <= e <= num[0],这个是很容易做到的,为了简化又不失去代表性,e选取2、3、4这三个数。我们就一起开始写吧:

首先,很容易的写下 int bSearch(int begin, int end, int e)

然后,很自然的定义 int mid, left = begin, right = end;

接下来怎么写呢?while(left < right)?while(left <= right)?while(mid == left)?while(mid == right)?………………真正一个写程序人会想纠结好一会儿,我们就选一个吧while(left < right)

下面,也很自然,min = (left + right) >> 1; 用位云算能节省一些时间呢!

现在呢?又是纠结的时候了吧?if(num[mid] > e)?if(num[mid] >= e)?我们也随便选一个吧,if(num[mid] > e)

其实,下面你会不断纠结……right = mid;这是正常人的写法,但是有时候也会看到别人写成right = mid - 1;我们也考虑下吧,但是现在我们就直接写right = mid;

有if了当然也会有else,然后理所当然 left = mid;同样记住还有一个选择left = mid + 1;

不错,整个while循环搞定了,最后就是返回了,写下return的时候是不是又纠结了?left?right?mid?算了,就写mid吧,整个程序就写好了,如下:

[cpp] view plaincopyprint?
  1. int bSearch(int begin, int end, int e)
  2. {
  3. int mid, left = begin, right = end;
  4. while(left < right)
  5. {
  6. mid = (left + right) >> 1;
  7. if(num[mid] > e) right = mid;
  8. else left = mid;
  9. }
  10. return mid;
  11. }

补充好整个程序后运行吧!查找2、3、4的时候都没有结果出现!!比如查4的时候,单步调试会发现当mid=4,left=4,right=5,接下来就一直在while里循环,保持不变!问题到底在哪?问题在很多地方,因为我们上面的遇到很多选择,没有结果是多个选择作用的共同的结果,通过修修补补也可以得到想要的结果,其它例子就不举了,直接说说本文章讨论的关键吧。我总结的二分无非就4种情况:YES_LEFT、YES_RIGHT、NO_LEFT、NO_RIGHT,分别代表:能找到且返回最左边的数的位置(如查找4的时候返回位置3)、能找到且返回最右边的数的位置(如查找4的时候返回位置4)、不能找到且返回左边与其接近的数的位置(如查找3的时候返回位置2)、不能找到且返回右边与其接近的数的位置(如查找3的时候返回位置3)。下面是我总结调试的代码:

对于YES_LEFT或者NO_RIGHT

[cpp] view plaincopyprint?
  1. int bSearch(int begin, int end, int e)
  2. {
  3. int mid, left = begin, right = end;
  4. while(left <= right)
  5. {
  6. mid = (left + right) >> 1;
  7. if(num[mid] >= e) right = mid - 1;
  8. else left = mid + 1;
  9. }
  10. return left;
  11. }

对于YES_RIGHT或者NO_LEFT

[cpp] view plaincopyprint?
  1. int bSearch(int begin, int end, int e)
  2. {
  3. int mid, left = begin, right = end;
  4. while(left <= right)
  5. {
  6. mid = (left + right) >> 1;
  7. if(num[mid] > e) right = mid - 1;
  8. else left = mid + 1;
  9. }
  10. return right;
  11. }

不做过多说明,单步调试自然会发现执行过程,要说明的是,两个程序都用了right = mid - 1; left = mid +1;用这个的前提是终止条件要是left <= right。要注意的是,有的二分查找不是只需要四种情况中的一种,而是组合使用,比如查找一个数,如果找到则×××不然则×××,如果是YES_LEFT || NO_RIGHT组合或者YES_RIGHT || NO_LEFT组合就直接用上面代码即可,否则就要综合用了,加一些判断等说明,因为用的时候不多,就不给出代码了,自己如果遇到可以试着写写,当成模板,以后直接用~

现在,是不是觉得二分查找很容易呢?如果总结过的话……

你真的会二分查找吗?相关推荐

  1. 你真的会写二分查找吗?

    上个月面试网易,面试官要我写个二分查找,查找与target相等的数字的下标...我心想:简单:刷刷一写,面试官说:你这不对,int mid  = (st + ed) >> 1;会溢出: 我 ...

  2. 你真的会写二分查找吗

    1 二分查找 二分查找是一个基础的算法,也是面试中常考的一个知识点.二分查找就是将查找的键和子数组的中间键作比较,如果被查找的键小于中间键,就在左子数组继续查找:如果大于中间键,就在右子数组中查找,否 ...

  3. 二分查找你确定真的会?生活中还能用来设计骗局?

    期末考要来了,最近小秋正在从零开始复习算法相关知识- 一道简单的算法题 帅地:听说你最近正在临时饱佛教复习各种算法? 小秋:对啊,算法太难了,把我头都搞大了,不过,感觉自己复习的好像还不错. 帅地:那 ...

  4. 今天会是有offer的一天么:面试时你真的会写二分查找么

    二分查找是一种非常常见的算法,在面试时会经常被问到.其输入是一个有序的数组,输出需要查找数字的下标(注意输入一定是有序的). 先说一下最基本的,有序数组中没有重复的元素. public class b ...

  5. 【基础算法】二分法(二分答案,二分查找),三分法,Dinkelbach算法,算法详解+例题剖析

    目录 一 . 二分法 二分搜索得要求: 二分查找步骤: 二分答案: 玄学的二分(二分答案) 二 . 三分法 例题 三.01分数规划问题相关算法与题目讲解(二分法与Dinkelbach算法) 一 . 二 ...

  6. 如何写出正确的二分查找?——利用循环不变式理解二分查找及其变体的正确性以及构造方式...

    序言 本文以经典的二分查找为例,介绍如何使用循环不变式来理解算法并利用循环不变式在原始算法的基础上根据需要产生算法的变体.谨以本文献给在理解算法思路时没有头绪而又不甘心于死记硬背的人. 二分查找究竟有 ...

  7. c语言二分法查找一个数_算法简解-二分查找

    读书不记录=没读,始终是我的信条·····最近因为要参加竞赛,发现自己真的差的很远,所以打算重新开始学习一遍算法及AI的相关数学知识,相信很多人都是闻数学,理工科色变,之前也是觉得上数理课太难了,真的 ...

  8. LeetCode Algorithm 704. 二分查找

    704. 二分查找 Ideas 这题想考察二分查找的来着. 对不起,真的对不起,作为Python爱好者,实在没忍住,就一行代码解决了. Code Python from typing import L ...

  9. ad09只在一定范围内查找相似对象_kafka日志段中的二分查找

    二分查找 Kafka 中直接接触索引或索引文件的场景可能不是很多.索引是一个很神秘的组件,Kafka 官方文档也没有怎么提过它.索引这个组件的源码还有一个亮点,那就是它应用了耳熟能详的二分查找算法来快 ...

最新文章

  1. 使用 MSBuild 和 Windows Installer XML 执行自动发布(转)
  2. Feign接口 多线程问题
  3. Eclipse Git下载问题:Internal error; consult Eclipse error log.
  4. lisp画垫圈_晓东CAD家园-论坛-LISP/VLISP程序库-[LISP程序]:俺的画内六角圆柱头螺钉的LISP程序-见附件 - Powered by Discuz!...
  5. 在线绘图(PS)(海报)
  6. TTC - Building a Better Vocabulary
  7. 工程伦理网课问答讨论整理
  8. C++数据结构之图的储存结构——十字链表
  9. 天天飞车六大研发经验
  10. HTTP请求详细过程
  11. 《山月记》一定有那么一刻,我们曾迷茫怀疑
  12. 基于单片机的通用定时器调度器SmartTimer
  13. 【解决方法】Pymongo insert 卡住
  14. Redis 9种数据结构
  15. 紫米10000mAh智能移动电源APP功能分析报告
  16. python创建模式对象_【python设计模式-创建型】单例模式
  17. 计算机专业的相关英语词汇,计算机专业英语单词大全
  18. Sentinel 相关知识点整理
  19. 华为鸿蒙手机用大卡还是小卡,教你解决SIM卡剪卡导致华为P8手机不识卡的问题...
  20. face++ API接口调用

热门文章

  1. go--基本数据类型
  2. 比特币这么火热,看看这篇比特币初学者指南
  3. 洛谷P1546 最短网络 Agri-Net
  4. 开源 免费 java CMS - FreeCMS2.1 会员站内信
  5. Oracle 实例恢复时 前滚(roll forward) 后滚(roll back) 问题
  6. servlet中的几个路径有关的方法
  7. WCF Data Service安全分析和说明
  8. 函数中参数有数组时注意的小问题(不一定要传递数组长度,不用返回数组,可以在函数中改变数组元素值)
  9. 爱奇艺大数据分析平台的演进之路
  10. zanePerfor 一款完整,高性能,高可用的前端性能监控系统,不要错过