首页 > 其他分享 >二分查找的个人朴素实用理解

二分查找的个人朴素实用理解

时间:2024-05-07 21:11:38浏览次数:9  
标签:二分 arr right mid 查找 目标值 朴素 left

背景

二分查找主要用于在有序数组中查找符合条件的特定值, 更进一步可以拓展到查找大于特定值的最小数和小于特定值的最大数的边界值问题, 在数据量很大的场景下合理利用有序或者说单调性这一特性大大提高查找效率, 能在对数时间内解决问题。

虽然理解起来很简单, 但是二分法是很常用也很巧妙的分治算法思想, 经常在某些复杂问题中可以利用数据有序特性来快速二分解决, 属于学起来简单但是能想到并且用到就很高效的算法, 姑且按照目前的个人理解记录一篇留待以后温习或补充完善。

主要思路

  • 数据必须是有序且存储在数组这种支持随机访问的连续数据结构, 在这个前提下才能通过下标随机访问中间位置数据, 且能根据判断结果来决定舍弃一半区域不会符合条件的数据, 比如在升序数组中如果arr[i]大于目标值就能确定所有下标大于i的区域值也都是大于目标值的, 下一步就应该在[0, i-1]范围去查找是否存在目标值;

  • 本文所有数据都假定按照升序排列;

  • 先介绍查找特定值是否存在的基础用途步骤:

    • 定义两个变量left和right, 初始值分别为0和arr.length - 1, 闭区间表示初始数组有效范围;
    • 取中间位置mid = (left + right) / 2, 一般为了防止加法数值溢出会采用 left + ((right - left) >> 1) 计算mid值;
    • 如果arr[mid]与目标值相等就直接返回结果;
    • 如果arr[mid]小于目标值就将right更新为mid-1重复第二步;
    • 如果arr[mid]大于目标值就将left更新为mid+1重复第二步;
  • 再介绍更进一步查找边界值(以大于特定值的最小数为例)的步骤:

    • 定义两个变量left和right, 初始值分别为0和length - 1, 在定义一个ans记录最终答案;
    • 取中间位置mid = (left + right) / 2;
    • 如果arr[mid]大于目标值, ans更新为mid, right更新为mid-1尝试去找是否存在更小的数符合条件;
    • 如果arr[mid]不大于目标值, left更新为mid+1, 重复第二步去更大值区域查找是否存在符合条件的数;
  • 这里不再赘述网上常见的所谓开区间、左闭右开等其它实现方式, 最开始学习掌握二分法的时候确实被循环结束条件和到底该更新成mid还是mid + 1或是mid - 1绕晕, 后面醒悟过来重要的是掌握这种思路, 只要记住一种实现方式解决问题就行, 其它花里花哨实现方式最终都是同一个结果没必要再费心思区分学习, 理解思路后看到其它方式自然也就能明白无非是不同细节而已并不影响最终结果和性能。

代码示例

  • 在升序数组中查找等于特定值的基础代码示例:

      /**
       * 在升序数组中查找是否存在与目标值相等的元素下标, 如果不存在则返回-1
       * 不考虑重复数据, 返回任意一个下标即可
       */
      public static int binarySearch(int[] arr, int target) {
          int left = 0, right = arr.length - 1;
          while (left <= right) {
              int mid = left + ((right - left) >> 1);
              if (arr[mid] == target) {
                  return mid;
              }
              if (arr[mid] > target) {
                  right = mid - 1;
              }
              else {
                  left = mid + 1;
              }
          }
          return -1;
      }
    
  • 在升序数组中查找大于特定值的最小数的代码示例:

      /**
       * 在升序数组中查找大于目标值的最小元素下标, 如果不存在则返回-1
       */
      public static int binarySearch(int[] arr, int target) {
          int left = 0, right = arr.length - 1, ans = -1;
          while (left <= right) {
              int mid = left + ((right - left) >> 1);
              if (arr[mid] > target) {
                  // 直接在符合条件的分支中更新ans, 不用再思考循环结束时怎么用left或right来计算结果, 代码可读性最高
                  ans = mid;
                  right = mid - 1;
              }
              else {
                  left = mid + 1;
              }
          }
          return ans;
      }
    

相关题目

后面再抽空整理一些典型的题目列出来, 不限于目前本人博客二分查找标签下的那些力扣题。

标签:二分,arr,right,mid,查找,目标值,朴素,left
From: https://www.cnblogs.com/coding-memory/p/18178399

相关文章

  • 二分法、冒泡排序
    【一】二分法二分法查找,也称为折半法,是一种在有序数组中查找特定元素的搜索算法思路:首先,从数组的中间元素开始搜索,如果该元素正好是目标元素,则搜索过程结束,否则执行下一步。如果目标元素大于/小于中间元素,则在数组大于/小于中间元素的那一半区域查找,然后重复步骤的操作。如......
  • 整体二分
    抽象。P3527[POI2011]MET-MeteorsByteotianInterstellarUnion有\(n​\)个成员国。现在它发现了一颗新的星球,这颗星球的轨道被分为\(m​\)份(第\(m​\)份和第\(1​\)份相邻),第\(i​\)份上有第\(a_i​\)个国家的太空站。这个星球经常会下陨石雨。BIU已经预测了接......
  • 如何查找Lenovo XClarity Controller 的 MIB 文件
    描述本文介绍了为运行LenovoXClarityController(LXCC)的Lenovo服务器查找和下载MIB文件的过程。程序转至数据中心支持。lenovo.com 。在搜索栏中,输入Lenovo服务器型号名称,然后单击自动搜索结果中正确服务器下的“下载” 。注意:在此示例中,将使用SR650。在“您在寻......
  • 【cmake】find_package设置查找路径
     1.find_package的作用与实例用来查找第三方依赖包的.cmake文件,并根据.cmake文件生成依赖包的头文件目录和库文件路径等;CMakeLists.txt实例find_package(ProtobufREQUIRED)include_directories(${PROTOBUF_INCLUDE_DIR})add_executable(mainsrc/main.cpp)target......
  • 《代码随想录》-2.二分查找
    前提:1.有序2.无重复//版本1intleft=0;intright=nums.size()-1;while(left<=right){intmiddle=left+(right-left)/2;//防止溢出if(nums[middle]>target){right=milddle-1;}elseif(nums[middle]<target{left=middle+1;}else{returnmiddle;......
  • 整体二分学习笔记
    最近准备学数据结构乱搞,接下来学k-dtree大致介绍可以使用整体二分解决的题目需要满足以下性质:1.询问的答案具有可二分性2.修改对判定答案的贡献互相独立,修改之间互不影响效果3.修改如果对判定答案有贡献,则贡献为一确定的与判定标准无关的值4.贡献满足交换律,结合律,具有可加......
  • 整体二分
    1概念在很多题目中,我们可以使用二分法来得出答案。但是如果说这一类题目有多次询问,并且多次询问分别二分会TLE时,我们就需要引入一个东西叫整体二分。整体二分的主要思路就是将多个查询一起解决,因此它是一种离线算法。整体二分的具体操作步骤如下:首先记\([l,r]\)为答案的......
  • 二叉查找树的接口设计
    /***************************************************filename:BianrySearchTree.c*author:[email protected]*date:2024/05/04*brief:二叉查找树的接口设计*note:None**CopyRight(c)[email protected]......
  • 整体二分学习笔记
    1.简介在一些题目中,可能存在一些题目,对于每次询问直接二分可能会TLE,此时就要用到整体二分整体二分是一种离线的方法,适用于如下情况:询问答案具有可二分性修改对判定答案的贡献相互独立,修改之间互不影响效果修改如果对判定答案有贡献,则该贡献是一个确定的与判定标准无关......
  • 二分图染色
    二分图booldfs(intu,intc){ if(color[u]==c) returntrue; elseif(color[u]==3-c) returnfalse; color[u]=c; for(intv:graph[u]) if(!dfs(v,3-c))returnfalse; returntrue;}习题:P1330封锁阳光大学解题思路按照题目要求,每一条......