基础算法01——二分查找(Binary Search)

二分查找(Binary Search)

  1. 二分查找算法:也称为折半查找 ,是一种在有序数组中查找特定元素的高效算法。
  2. 算法逻辑:
    • 每次取中间位置的值与待查关键字比较:
      • 如果待查关键字 比中间位置的值 ,则在有序数组的前半部分循环这个查找的过程
      • 如果待查关键字 比中间位置的值 ,则在有序数组的后半部分循环这个查找的过程
      • 每比较一次之后就更新中间位置的值,然后和带查找关键字比较
    • 一直重复上面的逻辑,(直到找到了待查找关键字)或者是(直到low的值比high的值大(数组遍历完成了都没有找到元素就结束循环了))才会结束循环

java代码演示

java 复制代码
public class ErFenChaZhao {
    public static void main(String[] args) {
        int[] array={2,4,6,7,9,102};
        int i = binarySearch(array, 102);
        if (i == -1){
            System.out.println("数组内无此元素!!!");
        }else {
            System.out.println("目标元素的位置是在数组下标为:"+ i + "的位置");
        }

    }

    /**
     * 二分查找
     * @param array:有序数组
     * @param a:目标元素
     * @return
     */
    public static int binarySearch(int[] array, int a){
       int low = 0; // 一开始最左边元素的位置
       int high = array.length-1; // 一开始最右边元素的位置
       int mid; // 中间元素
       while (low <= high){
           // 如果数组的元素是偶数的话,取的元素位置是中间两个元素的左边的元素,也就是小的那个元素(常用)
           // 如果要想取中间两个元素的右边的元素,中间元素取值表达式为 mid = (low+high+1)/2;
           mid = (low+high)/2;  // 中间元素的位置
           if (a == array[mid]){  // 把目标元素和中间元素作比较
               return mid;  // 返回中间元素的位置
           }else if (a > array[mid]){ // 如果目标元素比中间元素大,那么目标元素肯定在数组的右侧
               low = mid + 1;  // 把左边元素移动到中间元素的后一位
           }else {   // 如果目标元素比中间元素小,那么目标元素肯定在数组的左侧
               high = mid - 1; // 把右边元素移动到中间元素的后一位
           }
       }
        return -1;  // 找不到目标元素则返回-1
    };
}

注意事项:在获取中间索引值的时候(mid = (low+high)/2),可能整数溢出问题

问题分析:当low和high的值都特别大的时候,low+high就可能超过整数存储的最大值。

  • 解决办法:(替换计算(mid = (low+high)/2))
    • 修改计算式子:mid = (low+high)/2 = low + (high - low)/2
    • 使用无符号运算(这里是无符号右移一位):(low + high) >>> 1

二分查找可能的考法:

  1. 笔试题:手写二分查找算法。
  2. 选择或填空题 ,类似:
    • 有一个有序表为 1,5,8,11,19,22,31,35,40,45,48,49,50 当二分查找值为 48 的结点时,查找成功需要比较的次数
    • 使用二分法在序列 1,4,6,7,15,33,39,50,64,78,75,81,89,96 中查找元素 81 时,需要经过( )次比较
    • 在拥有128个元素的数组中二分查找一个数,需要比较的次数最多不超过多少次?

注意:

1.本文锁介绍的二分查找是以jdk中Arrays.binary Search的实现为例的。

2.实际上,二分查找有诸多变体,一旦使用变体的实现代码,则左右边界的选取会有变化。也就是说做题的时候要根据实际情况分析。

相关推荐
爱编程的化学家7 分钟前
代码随想录算法训练营第十一天--二叉树2 || 226.翻转二叉树 / 101.对称二叉树 / 104.二叉树的最大深度 / 111.二叉树的最小深度
数据结构·c++·算法·leetcode·二叉树·代码随想录
tqs_123458 分钟前
redis zset 处理大规模数据分页
java·算法·哈希算法
尚学教辅学习资料16 分钟前
基于Spring Boot的家政服务管理系统+论文示例参考
java·spring boot·后端·java毕设
杨杨杨大侠16 分钟前
Atlas Log 0.2.0 版本
java·github·apache log4j
快乐肚皮16 分钟前
TransmittableThreadLocal:穿透线程边界的上下文传递艺术
java
渣哥17 分钟前
别再无脑 synchronized 了!Java 锁优化的 7 个狠招
java
吃着火锅x唱着歌1 小时前
LeetCode 1446.连续字符
算法·leetcode·职场和发展
愚润求学1 小时前
【贪心算法】day10
c++·算法·leetcode·贪心算法
緈諨の約錠1 小时前
JVM基础篇以及JVM内存泄漏诊断与分析
java·jvm
Slaughter信仰1 小时前
深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)第十三章知识点问答(15题)
java·开发语言·jvm