二分查找

2023-02-25 09:43:55 浏览数 (1)

本页目录

  • 二分查找 基础版
    • 二分查找 基础班 优化点:无符号右移运算符>>>
  • 二次查找 改动版

需求:在有序数组A中,查找值target。如果找到了,返回target的索引,如果找不到返回-1

二分查找 基础版

解决思路:定义3个元素:左边界、有边界、中间索引。

代码语言:javascript复制
public class 二分查找 {
    // 前置了解:二分法,核心是获取中间索引,比如5个元素,中间的索引是2,(int)5/2 正好是2哦
    // 有3个重要元素:左边界、有边界、中间边界。其中参与对比的是中间边界。
    public static void main(String[] args) {
        int target = 3; // 定义目标元素
        int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        int leftIndex = 0; // 定义左边界
        int rightIndex = a.length - 1; // 定义右边界
        int middleIndex; // 定义中间边界
        int count = 0; // 自己搞一个计数器
        while (leftIndex <= rightIndex) { // 左边界必须要小于等于右边界。
            count  ;
            middleIndex = (leftIndex   rightIndex) / 2;
            if (a[middleIndex] < target) { // 目标在右边,左边逼近一位
                leftIndex = middleIndex   1;
            } else if (target < a[middleIndex]) { // 目标在左,右边逼近一位
                rightIndex = middleIndex - 1;
            } else { // 命中元素
                System.out.println("命中的索引是" middleIndex);
                break;
            }
        }
        System.out.println("总共循环了"   count   "次");
    }
}

二分查找 基础班 优化点:无符号右移运算符>>>

代码语言:javascript复制
middleIndex = (leftIndex   rightIndex) / 2;

这个代码看似没问题,第一次leftIndex是0,rightIndex三21亿,想加后再除以2,没问题。如果第二次是设置左边界使得leftIndex变成非0,就会导致(leftIndex rightIndex) 超过21亿的范围,经过计算,再除以2最终的结果就是(在Java中会把最高位定义为符号位)负数。请选择使用位运算>>>1 相当于除2。

第一位是符号位,1是负数,0是整数,原来是1的,右移1位,就被0代替了。不管如何,只要右移,结果都是整数!只要保证结果是正数,都可以使用无符号右移1位!

代码语言:javascript复制
middleIndex = (leftIndex   rightIndex) >>> 1;

二次查找 改动版

这一版本毫无意义。定义右边界不起命中作用,只用leftIndex 通过 1 去一步步逼近元素!如果 1 之后大于rightIndex,循环结束,没有命中目标!

代码语言:javascript复制
public class 二分查找改动版 {
    // 前置了解:二分法,核心是获取中间索引,比如5个元素,中间的索引是2,(int)5/2 正好是2哦
    // 有3个重要元素:左边界、有边界、中间边界。其中参与对比的是中间边界。
    public static void main(String[] args) {
        int target = 3; // 定义目标元素
        int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        int leftIndex = 0; // 定义左边界
        int rightIndex = a.length; // 定义右边界
        int middleIndex; // 定义中间边界
        int count = 0; // 自己搞一个计数器
        while (leftIndex < rightIndex) { // 左边界必须要小于右边界
            count  ;
            middleIndex = (leftIndex   rightIndex) >>> 1;
            if (a[middleIndex] < target) { // 目标在右边,左边逼近一位
                leftIndex = middleIndex   1;
            } else if (target < a[middleIndex]) { // 目标在左,右边逼近一位
                rightIndex = middleIndex;
            } else { // 命中元素
                System.out.println("命中的索引是" middleIndex);
                break;
            }
        }
        System.out.println("总共循环了"   count   "次");
    }
}

总结:使用基础版本即可,改动版毫无意义!本文当前的基础版其实还有优化点,循环判断的时候,直接判断是否命中元素,如果命中元素直接返回!不需要先判断左边界、右边界!嘿嘿,我知道,但我就不改!本站ChatGPT:你问问给我来份Java最优二分查找代码,也行!

特殊说明: 第三方平台不会及时同步本文章最新内容,如果觉得本文资料不全,可以访问本人Java博客搜索:标题类似的关键字 上述文章均是我实际操作后产出,烦请各位,请勿直接盗用!转载记得标注原文链接:www.zanglikun.com

0 人点赞