当前位置: 首页 > article >正文

数据结构——二分查找算法

1、算法描述

二分查找算法:需求:在有序数组A内,查找值target,如果找到则返回目标值的索引号,否则返回-1

算法描述
前提给定一个内含有n个元素的有序数组A,满足A0<=A1<=A2<=···<=An-1,一个待查找的值target
1设置i=0,j=n-1
2如果i>j,结束查找,没有找到
3设置m=floor((i+j)/2),m为中间索引,floor为向下取整(也就是小于等于(i+j)/2的最大整数)
4如果target<Am,设置j=m-1,跳转到第2步
5如果target>Am,设置i=m+1,跳转到第2步
6r如果Am=target,结束查找,找到目标值

2、算法实现

//Java写一个方法,传入一个数组和要查找的目标值
public static int erfenSearch(int[] a,int target){
   
       int i=0,j=a.length-1;      //设置两个指针的初值
       while(i<=j){               //在i到j范围内查找
             int m=(i+j)>>>1;
             if(target<a[m]){     //目标在左边
                j=m-1;            

            }else if(a[m]<target){ //目标在右边
                   i=m+1;
            }else{                  //找到了
                   return m;
            }
             
             reutrn -1;

       }

}

3、存在的问题

1、为什么循环中写i<=j,而不是i<j?

回答:如果只是写i<j,那么只有索引为m的参与比较,i和j为索引的元素就不会参与比较,比如查找到最后一个元素时i=j了,但是此时就不会进入循环去求m,从而就没办法比较i==j时的那个元素是否是目标值,而i==j就意味着i,j指向的元素也会参与比较

2、(i+j)/2为什么写成>>>1?

回答:如果i 和 j 变成了两个很大的正整数相加,那么得到的结果就有可能为负数,在二进制中,同一个二进制数,如果把最高位视为符号位,那么得到的结果就是负的,如果不视为符号位,那么得到的结果就是正常的,改变:使用无符号右移运算符来代替除2的过程。

右移:7的二进制数8位表示为0000 0111,右移之后变成0000 0011,也就是变成了3

16的二进制0001 0000,右移之后变成0000 1000 也就是变成了8

而这就能看成除2取整,(7除2取整就是3),同一个二进制可能表现出正整数,也会表现出负数,但是通过让其右移的方式,最终得到的结果都是正确的,此外,通过这种右移的方式还能适应其他语言

=(mi+j)>>>1;

3、为什么代码中都写成小于号,有什么好处?

回答:与数组的排序有关,数组属于升序还是排序,属于升序的就写小于号,能给人一种更加直观的感觉,写出来的代码与我们的思维更加一致,不过当然你不想这样写那也没关系,自己能够看得懂就行啦。

4、改版后的二分查找算法

//改写后的二分查找算法
public static int erfenSearch(int[] a,int target){
   
       int i=0,j=a.length;         //不进行减一
       while(i<j){                 //没有等于
             int m=(i+j)>>>1;
             if(target<a[m]){     
                j=m;               //直接等于m

            }else if(a[m]<target){ 
                   i=m+1;
            }else{              
                   return m;
            }
             
             reutrn -1;
       }
}

此时 j 所指向的位置不会参与运算,可以取一个递增的数组来做示范,这两种版本的二分法都需要掌握

注意:在改版后的不能在循环条件中添加等于号,否则当查找一个不存在的目标值时会陷入死循环中


http://www.kler.cn/news/8249.html

相关文章:

  • 架构重构的技巧
  • 十年程序老狗手写分布式服务架构:原理、设计与实战
  • 行为型模式-模板方法
  • 类的相关知识(二)const
  • 光度立体法检测原理讲解
  • 驾校预约课程管理系统设计与实现
  • 对象序列化流
  • 前端实现html转pdf
  • html+css实现的登录界面
  • 【计算机视觉·OpenCV】使用Haar+Cascade实现人脸检测
  • ESP32设备驱动-MLX90615红外测温仪驱动
  • Files的常用方法都有哪些?
  • 快速尝鲜Oracle 23c免费开发者版,惊喜多多
  • 分布式一致性协议
  • ctfshow web入门 爆破 21-28
  • P1011 [NOIP1998 提高组] 车站
  • Java设计模式 07-装饰者模式
  • 【Spring】2—IOC容器
  • 教你如何搭建物业-后勤管理系统,demo可分享
  • 静态路由的原理和配置(理论详细实验全面)
  • 周记录总结
  • 微积分——Rolle定理的理解(罗尔定理)
  • [Win32] 窗体暗色模式, C++, WinForm, WPF 使用方法, 判断颜色模式, 响应颜色变更消息, 设置标题栏暗色.
  • 初学对象存储OSS---学习笔记
  • CTP_将C++封装为Python可调用接口
  • Excel快捷键
  • CTF杂项提纲
  • leetcode每日一题:数组篇(1/2)
  • 乘法逆元讲解
  • 1004[递归]母牛的故事