说到二分查找可能大家会想到二分查找的基本模板类似这样的:

 /*** 二分查找的基本实现* 作用:对于一个已经从小到大排好序的数组找出目标元素的索引值* 时间复杂度为O(logn)* @param nums* @param target* @return*/public static int BinarySearch(int[] nums, int target){if(nums.length == -1)return -1;int left = 0;int mid = 0;int right = nums.length-1;while (left<=right){mid = left+(right-left)/2;if(nums[mid]==target)return mid;else if(nums[mid]<target)left = mid+1;elseright = mid-1;}return -1;}

然而这篇博文我想和大家一起看看二分查找在一些题目里不一样的用法

题目一:

来源LeetCode-278 第一个错误版本

你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。

假设你有 n 个版本 [1, 2, ..., n],你想找出导致之后所有版本出错的第一个错误的版本。

你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。

示例:

给定 n = 5,并且 version = 4 是第一个错误的版本。调用 isBadVersion(3) -> false
调用 isBadVersion(5) -> true
调用 isBadVersion(4) -> true所以,4 是第一个错误的版本。 

这题一看到就能让人联想到要用二分,可是这是差第一个错误版本,不像以前查出某一个数的索引这该怎么办呢,下面给出一位博主对于该题使用二分查找的思路

博文链接

思路部分如下:

因为一个版本是错误,其后面的所有版本都是错误的,所以我们可以用二分搜索,当取中点时,如果中点是错误版本,说明后面都是错误的,那第一个错误版本肯定在前面。如果中点不是错误版本,说明第一个错误版本肯定在后面。

这里直接使用min <= max的二分模板,因为我们其实要找的是好和坏的分界点,即这个点既不是好也不是坏,所以是找不到的,按照模板的特点,最后退出循环时,max指向小于目标的点,min指向大于目标的点,这里第一个坏的version较大,所以返回min

怎么样是不是感觉我去二分查找还能这么用有点意思吧

附上博文链接里大佬的java题解:

public class Solution extends VersionControl {public int firstBadVersion(int n) {int min = 1, max = n, mid = 0;while(min <= max){mid = min + (max - min) / 2;if(isBadVersion(mid)){max = mid - 1;} else {min = mid + 1;}}return min;}
}

题目二

LeetCode-287 寻找重复数

给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。

示例 1:

输入: [1,3,4,2,2]
输出: 2

示例 2:

输入: [3,1,3,4,2]
输出: 3

说明:

  1. 不能更改原数组(假设数组是只读的)。
  2. 只能使用额外的 O(1) 的空间。
  3. 时间复杂度小于 O(n2) 。
  4. 数组中只有一个重复的数字,但它可能不止重复出现一次。

这题我一拿到是蒙蔽的,空间复杂度和时间复杂度都受到了限制,对于我这种业余算法选手是真的有点难受了,搜了下题解,又是二分查找,其实我该想到的,O(1)的空间,小于O(n2)的时间,这些都算是LeetCode对于使用二分查找的提示了

题解链接

题解作者的思路:

这道题给了我们n+1个数,所有的数都在[1, n]区域内,首先让我们证明必定会有一个重复数,这不禁让我想起了小学华罗庚奥数中的抽屉原理(又叫鸽巢原理), 即如果有十个苹果放到九个抽屉里,如果苹果全在抽屉里,则至少有一个抽屉里有两个苹果,这里就不证明了,直接来做题吧。题目要求我们不能改变原数组,即不能给原数组排序,又不能用多余空间,那么哈希表神马的也就不用考虑了,又说时间小于O(n2),也就不能用brute force的方法,那我们也就只能考虑用二分搜索法了,我们在区别[1, n]中搜索,首先求出中点mid,然后遍历整个数组,统计所有小于等于mid的数的个数,如果个数大于mid,则说明重复值在[mid+1, n]之间,反之,重复值应在[1, mid-1]之间,然后依次类推,直到搜索完成,此时的low就是我们要求的重复值.

好吧小菜鸡拜倒在大佬的想法下了,行云流水,理所当然,题解的博主是用C++写的,下面附上我改的过了的java版代码:

class Solution {public int findDuplicate(int[] nums) {int low = 1, high = nums.length - 1;while (low < high) {int mid = low + (high - low) /2;int cnt = 0;for (int a : nums) {if (a <= mid) ++cnt;}if (cnt <= mid) low = mid + 1;else high = mid;}return low;}
}

上面这两道题加深了我对二分查找的认识,它确实不只是查找那么简单,用好了的话可以很神奇的解决一些问题.

因为发现自己在和朋友说题时还没理解透这两个题目和其对于二分查找的运用所以写下这篇博客备查.

二分查找以及其有趣的使用相关推荐

  1. 二分查找 递归与非递归实现

    二分查找将一个有序数组查找的时间复杂度从O(n)降到了O(logn). 首先是最基本的二分查找: public int binarySearch(int[] arr, int target, int ...

  2. 冒泡排序 | 快速排序 | 线性查找 | 二分查找等

    目录 排序算法:冒泡排序 排序算法:快速排序 数组的复制.反转.查询(线性查找.二分查找) 排序算法:冒泡排序 public static void main(String[] args){int[] ...

  3. 二分查找 二分答案 万字详解,超多例题,带你学透二分。

    很多人对二分感到很苦恼,很困惑,可能是因为二分的边界很难掌握,也许是判断条件难写- 然而,很幸运,你找到了这篇文章,仔细看下去,这篇文章将带你学透二分!!! 二分可以简单分为二分查找与二分答案. 可能 ...

  4. KLEE 使用(三)------ 使用 KLEE 为二分查找生成测试

    在上一篇博文中,我们展示了如何用 KLEE 来为一个简单程序生成测试用例.在这篇博文中,我们将展示如何使用 KLEE 中的数组和断言. 0x1 测试无序数组 如下是二分查找的算法实现: int bin ...

  5. tag数组-刷题预备知识-4.一通百通解决二分查找问题

    文章目录 1. 二分法查找法的基本思想 2. 二分查找的时间复杂度 3. 二分查找的几个模版 3.1 模板一: 标准的二分查找 3.2 模板二: 二分查找边界(左边界, 右边界, 或是左右边界) 3. ...

  6. LeetCode 395. 至少有 K 个重复字符的最长子串--二分查找+前缀和+优先队列

    至少有 K 个重复字符的最长子串 给你一个字符串 s 和一个整数 k ,请你找出 s 中的最长子串, 要求该子串中的每一字符出现次数都不少于 k .返回这一子串的长度. 示例 1: 输入:s = &q ...

  7. 算法图解/二分查找/简单查找/选择排序/递归算法/快速排序算法/

    大 O 表示法 大 O 表示法在讨论运行时间时,log 指的都是 log2 大 O 表示法指出了算法有多快,让你能够比较操作数,它指出了算法运行时间的增速,而并非以秒为单位的速度. 大 O 表示法指出 ...

  8. LeetCode简单题之二分查找

    题目 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1. 示例 1: 输入: n ...

  9. 二分查找模板全面总结

    二分查找 二分法的引入 情形1 1.X的平方根 2.搜索旋转排序数组 情形2 1.第一个错误的版本 2.寻找峰值 3.寻找旋转排序数组中的最小值 情形3 在排序数组中查找第一个和最后一个位置 当遇到查 ...

最新文章

  1. 2021年春季学期-信号与系统-第十二次作业参考答案-第一小题
  2. QEMU支持的网络模式
  3. berkeley db mysql_BDB:源自 Berkeley DB,事务型数据库
  4. (31)SystemVerilog语言编写D触发器
  5. c++如何解决大数组栈内存不够的问题
  6. 中国抗生素骨水泥行业市场供需与战略研究报告
  7. 字符串中第一次重复出现的数及第一次不重复出现的数
  8. python mysql_Python-操作 MySQL
  9. 3ds Max: Substance to V-Ray Workflows 3ds Max教程:从Substance到V-Ray工作流程 Lynda课程中文字幕
  10. 我的管理成长与思考 - 那些领导的真相,理解和思考
  11. 如何去除word文档中向下的箭头
  12. 非主流照片制作软件 Picasa有哪些主要的功能
  13. 2022引流新玩法,异业联盟打造商业闭环
  14. [汉化主题] Knowhow v1.1.16 – 响应式论坛知识库WordPress主题
  15. Altium Designer导出Gerber文件的一般步骤
  16. 基于JSP的“爱心宠物诊所”系统课程设计
  17. 区块链零知识证明:STARKs, Part II
  18. STM32入门笔记——PWM
  19. HIS接口--LIS 与 HIS 跳转URL
  20. 保证数据库质量安全:从0开始的数据库测试

热门文章

  1. 一嗨租车宣布获老虎基金等1.34亿美元投资
  2. maple 解代数方程组得多项式_利用修正影射法求组合KdV方程新的精确解
  3. C#项目中所有的窗体排版都乱了
  4. 从零开始,如何拥有自己的博客网站【华为云至简致远】
  5. Python是什么及小龙虾的面向对象
  6. 点餐系统的开发,php后台+微信小程序 实现完整的餐厅点餐系统。
  7. 关爱亚孤儿 我们在行动——九巨龙肥城市京欣学校走进聊城市东昌府区
  8. 机器学习入门之PCA与ICA
  9. 万卷书 - 欧洲的门户 [The Gates of Europe]
  10. Android图片上传服务器(File格式)