二分查找(Java版)

二分查找(基础版)

二分查找,即每次都先查询有序数组的中间索引位置的元素,如果该元素比目标元素大,则只需要再查找中间索引左边的元素,反之则只需要查询中间索引往右的位置。如在[1,2,3,4,5,6]中查找4这个元素,拿到中间索(0+5)/2向下取整到2,索引2的元素是3,目标元素4比3小,则我们只需要关注索引2往后的元素,即[4,5,6],一直查找到i>j的时候,说明整个数组遍历完成。

package 算法algorithm.二分算法;

/**
 * @author helijian
 * @program hlj
 * @date 2023/6/25 9:57
 * @description 在有序数组中查找目标元素,如果找到返回索引位置,找不到返回-1
 */

public class BinarySearch {
    /**
     * @param a
     * @param target
     * @return 存在的问题:①i <= j不能写成i < j,否则当i=j的时候不会比较
     * ②int m = (i + j) / 2,(i+j)/2 存在问题,如果j比较大,那第二次计算(i+j)/2时,
     * i+j可能会超出Integer.MAX_VALUE,导致计算出来的是一个负数(将最高位的1作为了符号位)
     */

    public static int BS(int[] a, int target) {
        int i = 0, j = a.length - 1;//设置两个指针,分别指向数组第一个元素和最后一个元素
        while (i <= j) {
//            int m = (i + j) / 2; //取中间位置
            int m = (i + j) >>> 1; //无符号右移
            if (target < a[m]) {   //目标值在左边
                j = m - 1;
            } else if (a[m] < target) {  //目标值在右边
                i = m + 1;
            } else {  //目标值等于m
                return m;
            }
        }
        return -1;
    }

    public static void main(String[] args) {
        int[] a = {1, 2, 3, 4, 5, 6, 7, 8};
        int m = BS(a, 9);
        System.out.println(m);
    }
}
二分查找(改进版)

基础版中,查询不到返回的是-1,但是返回的-1除了告诉我们没有查询到之外,没有任何其他意义。
改进:在一个有序数组中,查询目标元素,找到返回该元素的索引,找不到则返回将该元素插入该数组时应该插入的索引位置

分析:以下数组为例,分析如果目标元素不存在,其所插入的索引用什么去表示

在这里插入图片描述
在这个数组中找7这个元素:target=7

  • i=0,j=6,m=3 a[m]=a[3]=6<7
  • i=m+1=4,j=6,m=5 a[m]=a[5]=9>7
  • i=4,j=m-1=4,m=4 a[m]=a[4]=8>7
  • i=4,j=m-1=3,m=3,a[m]=a[3]=6!=target

再往后, i>j了,说明数组遍历完成,循环结束,没找到,通过步骤分析,我们可以知道,如果要将7插入数组,要插入到索引4的位置,而i正好指向这个位置,所以只需要返回i即可表示待插入元素要插入的索引位置,代码如下:

public static int BS(int[] a, int target) {
        int i = 0, j = a.length - 1;//设置两个指针,分别指向数组第一个元素和最后一个元素
        while (i <= j) {
//            int m = (i + j) / 2; //取中间位置
            int m = (i + j) >>> 1; //无符号右移
            if (target < a[m]) {   //目标值在左边
                j = m - 1;
            } else if (a[m] < target) {  //目标值在右边
                i = m + 1;
            } else {  //目标值等于m
                return m;
            }
        }
        return i;
    }
最左(右)元素查找

有这样一种场景,当一个有序数组的元素可以重复时,我们去查找某个元素,如果这个元素存在,希望查找到这个元素在数组中索引最小(大)的那个,如果不存在,则希望返回这个数组中 **小于等于(大于等于)**目标元素的最靠左的索引,如[1,2,3,3,5,6,6,8],如果查找3,希望找到第一个3,即索引为2的那个3,当找4的时候,4不存在,也希望找到最左边的3。

分析:

数组a=[1,2,3,3,5,6,6,8]中,找3

  • i=0,j=a.length-1=7,m=3,a[m]=a[3]=3
  • 找到了,但是不知道是不是最左边的3,此时继续循环
  • i=0,j=m-1=2,m=1,a[m]=a[i]=2<3,说明m的左边不需要再找了,增大i的值,i=m+1
  • i=m+1=2,j=2,m=2.a[m]=a[2]=3,此时a[m]=3,但还是不知道是不是左边的3,循环还没结束,继续循环
  • i=2,j=m-1=1,此时i>j了,退出循环,i此时指向的就是索引2的位置,所以返回i即可

代码实现:

 public static int BSLeftmost2(int[] a, int target) {
        int i = 0, j = a.length - 1;
        while (i <= j) {
            int m = (i + j) >>> 1;
            if (target <= a[m]) {
                j = m - 1;
            } else {
                i = m + 1;
            }
        }
        return i;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
二分查找(Binary Search)是一种在有序数组中查找某一特定元素的搜索算法。其基本思想是:每次取数组中间的元素与目标值进行比较,如果中间元素等于目标值,则查找成功;如果中间元素大于目标值,则在数组左半部分继续查找;如果中间元素小于目标值,则在数组右半部分继续查找。重复以上步骤,直到找到目标值或确定没有目标值为止。 以下是二分查找Java实现: ``` public static int binarySearch(int[] arr, int target) { int left = 0; int right = arr.length - 1; while (left <= right) { int mid = (left + right) / 2; if (arr[mid] == target) { return mid; } else if (arr[mid] < target) { left = mid + 1; } else { right = mid - 1; } } return -1; // 表示未找到目标元素 } ``` 在上述代码中,我们定义了一个 `binarySearch` 方法,该方法接收两个参数,一个是有序数组 `arr`,另一个是目标值 `target`。首先,我们定义两个指针 `left` 和 `right`,分别指向数组的左端和右端。然后,我们进入循环,每次计算中间元素的下标 `mid`,并判断中间元素与目标值的大小关系。如果中间元素等于目标值,则查找成功,返回其下标;如果中间元素小于目标值,则在数组右半部分继续查找,将 `left` 指针指向 `mid + 1`;如果中间元素大于目标值,则在数组左半部分继续查找,将 `right` 指针指向 `mid - 1`。最后,如果循环结束仍未找到目标元素,则返回 `-1`。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值