二分查找(Binary Search)是一种在有序数组中查找特定元素的高效算法。它的基本思想是将目标值与数组中间的元素进行比较,如果目标值小于中间元素,则在数组的左半部分继续查找,否则在右半部分查找,不断缩小搜索范围,直到找到目标值或确定目标值不存在为止。

二分查找也叫折半查找,比如在一个有序的数组里面找到目标值,它是一种查询效率比较高的算法,时间复杂度O(logn)。比如在下面数组找到 6.首先在定位到两侧,也就是最大值和最小值。并找到中间和目标值比较。

中间值是 23,比目标值更大,就要缩小范围,中间值作为最大值,在中间值左边的区域再找到中间值和目标值比较。

以此类推,一直缩小范围,直到找到目标值,或者搜索完数据。

二分查找模板

public static int binarySearch(int[] nums, int target) {
int left = 0;
int right = nums.length - 1; while (left <= right) {
int mid = left + (right - left) / 2; // 计算中间元素的索引
if (nums[mid] == target) {
return mid; // 找到目标值,返回索引
} else if (nums[mid] < target) {
left = mid + 1; // 目标值在右半部分
} else {
right = mid - 1; // 目标值在左半部分
}
} return -1; // 目标值不存在
}

left 和 right 记录最小值和最大值的下标,left + (right - left) / 2 是查询中间下标,有的查询下标直接使用(left + right)/2,这样可能会超出时间范围。通过 left = mid + 1 或者 right = mid - 1 不断缩小范围。

LeetCode 题解

33.搜索旋转排序数组

题目描述

解题思路

有序的数组在某个下标上进行旋转:

将旋转点之后的数据整体放在数组之前:

上面说二分查询只是针对有序的数组,这又不是一个有序的数组,但是数组分成两部分有序的数组。

  • 使用二分查找查看由 mid 分割出来的两部分 [l,mid] 和 [mid+1,r] 哪个部分是有序的,并根据有序的那个部分确定二分查找的左右边界

    • 如果[l,m-1]是有序数组,并且 target 的大小在 [l,mid] 中,则将搜索目标缩小至[l,mid - 1],否则范围在 [mid + 1,r] 中寻找。
    • 如果[mid,r]是有序数组,并且 target 的大小在 [mid + 1,r] 中,则将搜索目标缩小至[mid + 1,r],否则在[l,mid - 1] 中寻找。
public int search(int[] nums, int target) {
int length = nums.length;
if (length == 0) {
return -1;
}
if (length == 1) {
return nums[0] == target ? 0 : -1;
}
int left = 0,right = length-1;
while (left <= right) {
int mid = left + (right - left)/2;
if (nums[mid] == target) {
return mid;
}
if (nums[0] <= nums[mid]) {
if (nums[0] <= target && target < nums[mid]) {
right = mid -1;
} else {
left = mid + 1;
}
} else {
if (nums[mid] < target && target <= nums[length - 1]) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
return -1;
}

69.x的平方根

题目描述

解题思路

求解平法根,也就是k² <= x,也就是求解 k 最大整数值。对 x 进行二分查找。

  • 左边界是0,右边界是为x,每次二分查找到中间值 mid,mid 的平方的 x 的大小做对比。

    • 如果 mid 的平方小于等于 x,赋值结果,并且左边界移动到 mid + 1 的位置。
    • 如果 mid 的平方大于x,将有边界移动到 mid - 1 的位置。
    • 直达找到最优的解。
public int mySqrt(int x) {
if (x == 0 || x == 1) {
return x;
}
int left = 1;
int right = x;
int result = -1;
while (left <= right) {
int mid = left + (right - left)/2;
if ((long)mid * mid > x) {
right = mid - 1;
} else {
result = mid;
left = mid + 1;
} }
return result; }

153.寻找旋转排序数组中的最小值

题目描述

解题思路

旋转数组是要么全部有序,要么两个部分有序。每次做二分查找,每次mid和最右边值作比较,会出现两种情况。

第一种情况是 nums[pivot] < nums[high],如上图所示,此时最小值应该在 piot 的左侧,height 缩进到 pivot 的位置。

第二种情况是 nums[piot] > num[height], 如上图所示,此时最小值应该在 piot 的右侧,low 缩进到 piot 的位置。

class Solution {
public int findMin(int[] nums) {
int low = 0,height = nums.length-1;
while (low < height) {
int mid = low + (height - low)/2;
if (nums[mid] < nums[height]) {
height = mid;
} else {
low = mid + 1;
}
}
return nums[low];
}
}

367.有效的完全平方数

题目描述

解题思路

  • 判断一个数是否是完全平方数,需要找到他的开根数。
  • 使用二分法查找,如果 num < 2 返回true,因为 0 和都是完全平方数。
  • 2 为 left,num 为 right,通过 left + (right - left)/2 找到中间值
    • 如果 mid² = num,返回true。
    • 如果 mid² < num,left = mid + 1。
    • 如果 mid² > num ,right = mid - 1。
public boolean isPerfectSquare(int num) {
if (num <= 2) {
return true;
}
int left = 2,right = num/2,y;
long square;
while (left <= right) {
y = left + (right - left)/2;
square =(long) y * y;
if (square == num) {
return true;
}else if (square > num) {
right = y - 1;
}else {
left = y + 1;
}
}
return false;
}

总结

搜索有序的数组的元素,使用二分查找是一个高效率的查询方法。定位左右两侧最大值和最小值,找到中间值。然后通过目标值和中间值做对比,缩小搜索范围,直到搜索找到符合条件数据。

有时候无需全部有序,两部分有序也是可以通过二分查找找到符合要求的数据。

图解 LeetCode 算法汇总——二分查找的更多相关文章

  1. 【算法】二分查找法&大O表示法

    二分查找 基本概念 二分查找是一种算法,其输入是一个有序的元素列表.如果要查找的元素包含在列表中,二分查找返回其位置:否则返回null. 使用二分查找时,每次都排除一半的数字 对于包含n个元素的列表, ...

  2. javascript数据结构与算法---检索算法(二分查找法、计算重复次数)

    javascript数据结构与算法---检索算法(二分查找法.计算重复次数) /*只需要查找元素是否存在数组,可以先将数组排序,再使用二分查找法*/ function qSort(arr){ if ( ...

  3. 分治算法(二分查找)、STL函数库的应用第五弹——二分函数

    分治算法:二分查找!昨天刚说不写算法了,但是突然想起来没写过分治算法的博客,所以强迫症的我…… STL函数库第五弹——二分函数lower_bound().upper_bound().binary_se ...

  4. 算法图解第一章_二分查找_python

    什么是二分查找? 我们先玩一个游戏. 在1至100之间我写下一个数,由你来猜测这个数是多少.我会告诉你高了还是低了. 最简单的办法就是每次取一半. 例如 "50""低了& ...

  5. 算法图解 - 第1章 二分查找 与大O

    例子:猜一个1到100之间的数,最多猜几次? # 最糟糕的猜法:一个一个的猜 - 最多查找次数: n  - 运行时间: O(n) # 二分查找:在有序的一组数中猜一个数,对半猜.找到返回其位置(索引) ...

  6. python算法之二分查找

    说明:大部分代码是在网上找到的,好几个代码思路总结出来的 通常写算法,习惯用C语言写,显得思路清晰.可是假设一旦把思路确定下来,并且又不想打草稿.想高速写下来看看效果,还是python写的比較快.也看 ...

  7. JS算法之二分查找

    二分查找法主要是解决「在一堆有序的数中找出指定的数」这类问题,不管这些数是一维数组还是 多维数组,只要有序,就可以用二分查找来优化. 二分查找是一种「分治」思想的算法,大概流程如下: 1.数组中排在中 ...

  8. 数据结构与算法之PHP查找算法(二分查找)

    二分查找又称折半查找,只对有序的数组有效. 优点是比较次数少,查找速度快,平均性能好,占用系统内存较少: 缺点是要求待查表为有序表,且插入删除困难. 因此,折半查找方法适用于不经常变动而查找频繁的有序 ...

  9. python实现查找算法:二分查找法

    二分查找算法也称折半查找,基本思想就是折半,和平时猜数字游戏一样,比如猜的数字时67,猜测范围是0-100,则会先猜测中间值50,结果小了,所以就会从50-100猜测,中间值为75,结果大了,又从50 ...

  10. Java查找算法之二分查找

    二分查找是一种查询效率非常高的查找算法.又称折半查找. 一.算法思想 有序的序列,每次都是以序列的中间位置的数来与待查找的关键字进行比较,每次缩小一半的查找范围,直到匹配成功. 一个情景:将表中间位置 ...

随机推荐

  1. 一篇文章带你详细了解axios的封装

    axios 封装 对请求的封装在实际项目中是十分必要的,它可以让我们统一处理 http 请求.比如做一些拦截,处理一些错误等.本篇文章将详细介绍如何封装 axios 请求,具体实现的功能如下 基本配置 ...

  2. Nucleic Acids Research上关于生物医学分析Galaxy平台在几个独立面上的最新发展。 该平台的官方主服务器拥有超过124000注册用户,每月新注册用户~2000。平均而言,......

    本文分享自微信公众号 - 生信科技爱好者(bioitee).如有侵权,请联系 support@oschina.cn 删除.本文参与"OSC源创计划",欢迎正在阅读的你也加入,一起分 ...

  3. Bio+IT 爱好者社区,欢迎你!

    生物信息学是一个跨学科的大领域,一直以来,做生物信息分析的工程师都需要跟 IT 打交道. 现实问题是,有很多生物学.医学.遗传学背景的 Bio 人对生物领域拥有非常专业的知识经验,而对 IT 领域知之 ...

  4. C# 客户端程序 Visual Studio 远程调试方法

    传统桌面客户端的远程调试相比UWP,ASP等项目来说,配置比较麻烦,因为它是非部署的应用程序,原理是复制编译的文件到远程计算机,通过网络来连接和VS的通信,本文主要讲述WPF,WinForm应用程序的 ...

  5. Java中的金钱陷阱

    前言 有多少小伙伴是被标题 骗 吸引进来的呢,我可不是标题党,今天的文章呢确实跟"金钱"有关系. 但是我们说的不是过度追求金钱而掉入陷阱,而是要说一说在Java程序中,各种跟金钱运 ...

  6. 文档在线预览(四)将word、txt、ppt、excel、图片转成pdf来实现在线预览

    @ 目录 事前准备 1.需要的maven依赖 2.后面用到的工具类代码: 一.word文件转pdf文件(支持doc.docx) 二.txt文件转pdf文件 三.PPT文件转pdf文件(支持ppt.pp ...

  7. CANoe工具的安装

    CANoe是德国Vector公司为汽车总线的开发而设计的一款总线开发环境,全称叫CAN open environment,用于分析和模拟CAN(Controller Area Network)和LIN ...

  8. NameError: name 'List' is not defined

    当在python出现该问题是,使用from typing import List.

  9. 把langchain跑起来的3个方法

    使用LangChain开发LLM应用时,需要机器进行GLM部署,好多同学第一步就被劝退了,那么如何绕过这个步骤先学习LLM模型的应用,对Langchain进行快速上手?本片讲解3个把LangChain ...

  10. 了解前端中的BFC(块级格式化上下文)

    BFC(块级格式化上下文) 什么是BFC 指的是一个块级渲染作用域,该区域内拥有一套完整的规则来约束块级盒子的布局,且与区域外部无关. 为什么要使用BFC 当一个盒子不设置高度,当其中的子元素都浮动时 ...