最基本的二分查找算法


「搜索区间」是 [left, right]
nums[mid] == target 时可以立即返回

int binary_search(int[] nums, int target) {int left = 0, right = nums.length - 1; while(left <= right) {int mid = left + (right - left) / 2;//防止大数溢出if (nums[mid] < target) {left = mid + 1;} else if (nums[mid] > target) {right = mid - 1; } else if(nums[mid] == target) {// 直接返回return mid;}}// 直接返回return -1;
}

普通版寻找左侧边界的二分查找

「搜索区间」是 [left, right)
{1,2,2,2,3}
nums[mid] == target 时不要立即返回,要收紧右侧边界以锁定左侧边界

int left_bound(int[] nums, int target) {int left = 0, right = nums.length - 1;while (left <= right) {int mid = left + (right - left) / 2;if (nums[mid] < target) {left = mid + 1;} else if (nums[mid] > target) {right = mid - 1;} else if (nums[mid] == target) {// 别返回,锁定左侧边界right = mid - 1;}}// 最后要检查 left 越界的情况if (left >= nums.length || nums[left] != target)return -1;return left;
}

普通版寻找右侧边界的二分查找

「搜索区间」是 [left, right)
{1,2,2,2,3}
nums[mid] == target 时不要立即返回,收紧左侧边界以锁定右侧边界

int right_bound(int[] nums, int target) {int left = 0, right = nums.length - 1;while (left <= right) {int mid = left + (right - left) / 2;if (nums[mid] < target) {left = mid + 1;} else if (nums[mid] > target) {right = mid - 1;} else if (nums[mid] == target) {// 别返回,锁定右侧边界left = mid + 1;}}// 最后要检查 right 越界的情况if (right < 0 || nums[right] != target)return -1;return right;
}

排除法思考二分法


1、确定搜索区间初始化时候的左右边界,有时需要关注一下边界值。在初始化时,有时把搜索区间设置大一点没有关系,但是如果恰好把边界值排除在外,再怎么搜索都得不到结果。

2、无条件写上 while (left < right) ,表示退出循环的条件是 left == right,对于返回左右边界就不用思考了,因此此时它们的值相等;

3、先写下取整的中间数取法,然后从如何把 mid 排除掉的角度思考 if 和 else 语句应该怎样写。

(这里建议写两个注释。)

  • 一般而言,我都会把**“什么时候不是目标元素”**作为注释写在代码中,提醒自己要判断正确,这一步判断非常关键,直接影响到后面的代码逻辑。
  • 然后接着思考 mid 不是解的情况下,mid 的左右两边可能存在解,把下一轮搜索的区间范围作为注释写进代码里,进而在确定下一轮搜索区间边界的收缩行为时,不容易出错。

if 有把握写对的情况下,else 就是 if 的反面,可以不用思考,直接写出来。

** 说明:这种思考方式,就正正好把待搜索区间从逻辑上分成两个区间,一个区间不可能存在目标元素,进而在另一个区间里继续搜索,更符合“二分”的语义。**

4、根据 if else 里面写的情况,看看是否需要修改中间数下取整的行为。


上面已经说了,只有看到 left = mid 的时候,才需要调整成为上取整,记住这一点即可,我因为刚开始不理解这种写法,遇到很多次死循环,现在已经牢记在心了。

5、退出循环的时候,一定有 left == right 成立。有些时候可以直接返回 left (或者 right,由于它们相等,后面都省略括弧)或者与 left 相关的数值,有些时候还须要再做一次判断,判断 left 与 right 是否是我们需要查找的元素,这一步叫“后处理”。

// 有可能区间内不存在目标元素,因此还需做一次判断if (nums[left] == target) {return left;}return  -1;
public int searchInsert(int[] nums, int target) {int len = nums.length;if (len == 0) {return 0;}int left = 0;// 因为有可能数组的最后一个元素的位置的下一个是我们要找的,故右边界是 lenint right = len;while (left < right) {int mid = (left + right) >>> 1;// 小于 target 的元素一定不是解if (nums[mid] < target) {// 下一轮搜索的区间是 [mid + 1, right]left = mid + 1;} else {right = mid;}}return left;}


二分查找模板 一般步骤

与其他二分查找的比较


[总结]

1.普通版

-左右移动下标时,mid下标对应的值已经作为比较,故坐标更新时需要加一减一

2.防止大数溢出
  • mid = left + (right - left) / 2
3.完整掌握二分查找需要注意细节,善用排除法

参考链接:https://github.com/Arthashuo/fucking-algorithm/blob/master/%E7%AE%97%E6%B3%95%E6%80%9D%E7%BB%B4%E7%B3%BB%E5%88%97/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E8%AF%A6%E8%A7%A3.md

参考链接:https://leetcode-cn.com/problems/search-insert-position/solution/te-bie-hao-yong-de-er-fen-cha-fa-fa-mo-ban-python-/

[算法][二分查找][排除法]相关推荐

  1. java 二分查找_计算机入门必备算法——二分查找法

    1.引言 笔者对于计算机的研究一直停滞不前,近期想对一些算法进行复习和进一步的研究,每天都会更新一个新的算法,算法有难有易,层层递进.不希望能学的有多么高深,只希望在一些最基本的算法上有编码的思路,或 ...

  2. 90%的程序员都写错的算法-二分查找万能模版

    新的角度看二分 二分就是将数组分为两段 因此,问题的最终目标是找出蓝红边界 朴素算法 红色指针一开始指向最右超出范围处,随后不断向左移动,直到找到蓝红边界:或者蓝色指针- 时间复杂度O(n)O(n)O ...

  3. 数据结构与算法 | 二分查找

    假如我们在图书馆中整理书记,书按照序号有序排序,序号不连续,当我们需要从书堆中找到特定序号的书时,如果一本一本查找的话,我们可能需要查找N次.但如果我们先找到中间的书,将书分成两堆,与待查书对比,待查 ...

  4. 数据结构与算法——二分查找与二叉排序树

    文章目录 1.预备知识 1.1 题目目录 1.2 二分查找 1.3 递归二分查找 1.4 循环二分查找 1.5 二叉查找(排序)树 1.6 二叉搜索树的代码实现 2.搜索插入位置 2.1 题目描述 2 ...

  5. 【算法】算法 二分查找 二分查找 查找多个相同的值

    文章目录 1.概述 2.算法 3.查找多个相同的值 4. 非递归 本文为博主九师兄(QQ:541711153 欢迎来探讨技术)原创文章,未经允许博主不允许转载. 1.概述 参考视频:https://w ...

  6. php折半查找算法,二分查找 [折半查找] 算法 PHP 版

    查找表:就是同一类型的数据元素构成的数据集合 有静态表和动态表 本文实现PHP版的二分查找算法[本算法仅用于顺序存储的查找表] /** * Created by PhpStorm. * User: 1 ...

  7. Java算法 -- 二分查找:查找目标元素最左的位置和最右的位置、局部最小值问题求解

    1. 二分查找 二分查找也是一种在数组中查找数据的算法.它只能查找已经排好序的数据.二分查找通过比较数组中间的数据与目标数据的大小,可以得知目标数据是在数组的左边还是右边.因此,比较一次就可以把查找范 ...

  8. NTC测温中 经典温度查表算法--二分查找法

    说明: 二分查找法的优点:查找速度快 1024个长度的表最长只需10次查表就能得出结果 在用NTC测试温度的方案中,NTC的温度表的长度一般是100-200 有些达到400-500的长度 在这种情况下 ...

  9. 查找算法——二分查找(原理+源码)

    1,原理 二分查找又称折半查找,只适用于有序数组.二分查找原理很简单,针对有序数组的查找效率也很高.具体原理为,每次拿目标数值(以下用value表示)与数组中间位置的数据(以下用arry[mid]表示 ...

最新文章

  1. 文化内涵和历史深度:PC
  2. mongodb学习篇
  3. JZOJ 5926. 【NOIP2018模拟10.25】naive 的图
  4. mammary cancer关联规则挖掘详解
  5. 华三交换机接口配置access_二层交换——交换机的基础和VLAN
  6. 用于MPEG-4视听流的RTP负载格式
  7. 使用 Storyboard Segue 实作 UIViewController 的切换 (实例)
  8. java到底是值传递还是引用传递?
  9. 【winfrom】事件与委托
  10. 经典算法——五大常用算法
  11. 如何将图片调为半色调_为什么我们喜欢粗糙的唱片,半色调网点和其他缺陷?
  12. iphone抓包调试神器—Stream安装和使用
  13. Part Ⅴ Entertainment 娱乐活动??
  14. 谈谈创业这点事(3)
  15. 用关键词搜索店铺列表详情
  16. 【转】 机器学习入门——浅谈神经网络
  17. office修复找不到msi_office2013安装出错,老是出现找不到officeMUI.msi或则officeMUI.xml等,是什么原 - Microsoft Community...
  18. c++使用hiredis库操作redis讲解
  19. 互联网最新报告出炉!程序员必看系列!
  20. mytrader-开源股票期货金融软件+支持C/C++/Python/Excel/VBA/麦语言的量化分析交易平台

热门文章

  1. 做最好的自己——读书笔记
  2. 01-subgradients_notes
  3. asp.net core 在Ubuntu 运行
  4. [FZYZOJ 1038] 隧道
  5. 入门训练 Fibonacci数列
  6. pythonweb服务器部署iis_IIS部署python Web(FLASK试例)
  7. macos -bash: yarn: command not found/-bash: cnpm: command not found
  8. java 字符串数组转int数组_java怎么把字符型数组转换为int型?
  9. codeblocks如何导入项目_T3如何利用系统工具导入导出复制存货档案
  10. 视频转换工具(命令行)