数据结构与算法 二分查找

目录

二分查找

1、何为二分查找

2、编写二分查找代码

3、问题解决

4、选择题目1


二分查找

1、何为二分查找

当给我们这样一个数的时候 [1,4,6,7,9];

如果正常一个一个进行查找需要 最好的情况是第一个就是 最坏的情况是最后一个即查找5次

当个数不多的时候,花费时间是可以接受的,但是当个数很大的时候

例如1亿的个数的时候 最坏的情况就是要查找1亿次,花费的时间就无法接受了

因此二分查找就是为了解决这个问题, 这里有个结论即使个数很大 二分查找最多就执行32次

(因为int的取值是-2^31 --- 2^31-1 )

1亿次跟32次比较,显而易见二分查找的效率是非常高效的

二分查找针对的是一个有序的集合。每次都通过跟区间的中间元素对比,将待查找的区间缩小为之前的一半,直到找到要查找的元素,或者区间被缩小为 0。

2、编写二分查找代码

思路:

  1. 前提:有已经排序好的数组A (这里将的是递增排序)

  2. 定义左边界L、右边界R,确定搜索范围,循环执行二分查找(3,4步)

  3. 获取中间索引 m= (L+R)/2 向下取整 ---当然是int直接写就自动向下取整了

  4. 中间索引的值 A[m] 和待查找的数值T进行比较

    ① A[m] == T 表示找到,返回中间索引m即可

    ② A[m] < T ,中间值左侧的其他元素都小于T ,无序比较 ,去中间索引右边去找,m+1 设置为左边界 ,重新查找

    ③ A[m] > T ,中间值右侧的其他元素都大于T,无序比较, 去中间索引左边去找 m-1 设置为右边界,重新查找

5.当L>R ,表示没有找到,结束循环

package com.sofwin.controller;
​
/**
 * @packageName: com.sofwin.controller
 * @author: wentao
 * @date: 2022/10/26 9:59
 * @version: 1.0
 * @email 1660420659@qq.com
 * @description: 手写二分查找
 */
public class BinarySearch {
    public static void main(String[]args){
        int[] array = {1, 4, 5, 23, 31, 43, 47, 54};
        int target = 47;
        int index = binarySearch(array, target);
        System.out.println(index);
    }
​
    public static  int binarySearch(int[] arr, int tar) {
        //左边界L  右边界R  中间值M
        int l = 0, r = arr.length-1, m;
        while (l <= r) {
            //取中间值
            m = (l + r) / 2;
            if (arr[m] == tar) {
                return  m;
            }else if (arr[m] > tar) {
                r = m - 1;
            }else {
                l = m+1;
            }
        }
        return  -1;
    }
}
​

3、问题解决

当L和R都特别大的时候,当L+R相加可能会超过int的取值范围,造成整数溢出,因此我们需要改进一下代码

public class IntegerOverFlow {
    public static void main(String[]args){
        int l = 0;
        int r = Integer.MAX_VALUE;
        int m = (l + r) / 2;
        //第一不会出现问题
        System.out.println(m); //1073741823
​
       // 但是当要查找的是在中间值的右侧的时候
        l = m + 1;
        //这个时候l+r就超出了int的取值返回 会造成值的溢出
        m = (l + r) / 2;
        System.out.println(m); //-536870912
      }
   }
 这种情况就会造成溢出问题

方式一:数学问题转换

  l = m + 1;
        //这个时候l+r就超出了int的取值返回 会造成值的溢出
        //(l + r) / 2 ==> l / 2 + r / 2
        // l - l / 2 + r / 2  ==> l + (r - l) / 2
        m = l + (r - l) / 2;
        System.out.println(m); //1610612735

方式二:无符号右移1位

当数字为正数的时候 无符号右移1位就相当于除以2 (注意负数不成立)

//解决整数溢出的方式2 无符号的右移 并且效率比除法的效率还高
        l = m + 1;
        //这个时候l+r就超出了int的取值返回 会造成值的溢出
        //无符号的右移,就是将符号位看着普通的位数
        //因为l 和 r都是整数 因此就不会会出现溢出现象了
        m = (l + r) >>> 1;
        System.out.println(m);

4、选择题目1

1.有一个有序表为 1,5,8,11,19,22,31,35,40,45,48,49,50 当二分查找值为48结点的时候,查找成功需要比较的次数

4次

2.使用二分法在序列 1,4,6,7,15,33,39,50,64,78,75,81,89,96 中查找元素81时需要经过几次

4次

上面两题的技巧 奇数就取中间值 偶数就取中间值左面的

3.在拥有128个元素的数组中二分查找一个数,需要比较词素最多不超过多少次

7次

查到1即可 128除以2 整数直接输出 小数取出小数+1

注意

JDK的Arrays.binarySearch()方法也可以实现二分查找

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值