数据结构算法,手把手教你实现二分查找

写在前面

二分查找我就不多做介绍,只要是个程序员都知道这个经典的算法。我主要想介绍的是二分查找的实现方式,供大家学习。

总体思路

  1. 前提必须是有序的数组,如果不是有序数组则不能使用二分查找。我这里举例是升序的数组。降序的数组实现思路相反即可。
  2. 找中间索引对应的值,然后对比。如果和中间索引的值相等,则返回中间索引的下标;如果小于中间索引值,则在中间索引值左边的区间查找;如果大于中间索引值,则在中间索引值右边的区间查找;
  3. 如果都没有找到,则返回-1;

使用递归法实现

public static void main(String[] args) throws Exception {
    //创建一个从0到一亿的数组
    int n = 100000000;
    int[] nums = new int[n];
    for (int i = 0; i < n; i++) {
        nums[i] = i;
    }
    //数组最后一个索引值
    int end = nums.length - 1;
    //使用二分查找查找目标值1在数组中的下标
    long starTime = System.nanoTime();
    int search = new Main().binarySearch(nums, 0, end / 2, end, 1);
    long endTime = System.nanoTime();
    out.println("耗时:" + (endTime - starTime) / 1000 + "微秒,下标值是:" + search);
}
/*    
 * 二分查找
 *
 * @param nums   数组
 * @param star   开始索引
 * @param mid    中间索引
 * @param end    末尾索引
 * @param target 目标值
 * @return 目标索引的下标;如果没有查询到结果则返回-1
 * @date 2020/4/29 11:22
 */
public int binarySearch(int[] nums, int star, int mid, int end, int target) {
    //递归终止条件,如果开始索引比末尾索引要大则证明找不到,返回-1
    if (star > end) {
        return -1;
    }
    int midVal = nums[mid];
    if (midVal == target) {
        return mid;
    } else if (midVal > target) {
        return binarySearch(nums, star, (star + mid - 1) / 2, mid - 1, target);
    } else {
        return binarySearch(nums, mid + 1, (mid + 1 + end) / 2, end, target);
    }
}

耗时结果如下:

//耗时:72微秒,下标值是:1
//耗时:82微秒,下标值是:9
//耗时:86微秒,下标值是:1000

从这里可以看出有一个特点:耗时几乎都差不多。

递归法的缺点

我们都知道如果递归深度太深,会导致栈溢出。有没有不用递归的方式也能实现二分查找的方法呢,答案是肯定有的。

使用迭代法实现

public static void main(String[] args) throws Exception {
    //创建一个从0到一亿的数组
    int n = 100000000;
    int[] nums = new int[n];
    for (int i = 0; i < n; i++) {
        nums[i] = i;
    }
    //使用二分查找查找目标值1在数组中的下标
    long starTime = System.nanoTime();
    int search = new Main().binarySearch(nums, 100);
    long endTime = System.nanoTime();
    out.println("耗时:" + (endTime - starTime) / 1000 + "微秒,下标值是:" + search);
}

/**
 * 二分查找
 * @param nums 数组
 * @param target 目标值
 * @return 目标索引的下标;如果没有查询到结果则返回-1
 * @date 2020/4/29 13:51
 */
public int binarySearch(int[] nums, int target) {
    //左指针
    int left = 0;
    //右指针
    int right = nums.length - 1;
    //中间索引下标
    int mid;
    //只要左指针小于等于右指针就一直循环
    while (left <= right) {
        //获取中间索引下标,有些人喜欢写成 left+(right-left)/2;意思是一样的
        mid = (left + right) / 2;
        int midVal = nums[mid];
        //判断中间值与目标值是否相等,相等则找到了,返回下标
        if (midVal == target) {
            return mid;
        }
        //如果中间值大于目标值,证明目标值在左边,把右指针移到中间索引前面
        else if (midVal > target) {
            right = mid - 1;
        }
        //如果中间值小于目标值,证明目标值在中间值右边,因为是升序排序的数组嘛,把左指针移到中间索引的后面
        else {
            left = mid + 1;
        }
    }
    //如果左指针大于右指针了,跳出循环,证明找不到目标值,返回-1
    return -1;
}

结果也是可以的:

//耗时:65微秒,下标值是:100
//耗时:67微秒,下标值是:200

这样就不担心会出现栈溢出的问题。

总结

二分查找是一种比较经典的算法。通过每次与中间值的对比,然后缩小搜索的范围,以此提高了效率。
如果面试官问了时间复杂度是多少呢?答案是:O(log2n)
在这里插入图片描述

能力有限,如果有什么错误或者不当之处,请大家批评指正,一起学习交流!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二分查找是一种常见的搜索算法,用于在有序数组或有序列表中快速定位特定值的位置。这种算法的基本思想是将目标值与数组中间元素进行比较,根据比较结果将搜索范围缩小一半,直到找到目标值或确定目标值不存在为止。 以下是二分查找算法的基本步骤: 1. 初始化左边界 left 和右边界 right,分别指向数组的第一个元素和最后一个元素。 2. 计算中间位置 mid,可以使用公式 mid = (left + right) / 2。 3. 比较中间位置的值与目标值 target: - 如果中间位置的值等于目标值,则找到目标值,返回索引。 - 如果中间位置的值大于目标值,则目标值可能在左半部分,更新右边界为 mid - 1。 - 如果中间位置的值小于目标值,则目标值可能在右半部分,更新左边界为 mid + 1。 4. 重复步骤 2 和步骤 3,直到找到目标值或搜索范围为空(即 left > right)。 以下是一个使用二分查找算法在有序数组中查找目标值的示例代码(使用递归实现): ```python def binary_search(arr, target, left, right): if left > right: return -1 mid = (left + right) // 2 if arr[mid] == target: return mid elif arr[mid] > target: return binary_search(arr, target, left, mid - 1) else: return binary_search(arr, target, mid + 1, right) ``` 你可以将目标值、数组以及左右边界作为参数传递给该函数来执行二分查找。如果目标值存在于数组中,该函数将返回目标值的索引;否则,返回 -1 表示未找到。 希望这能回答你的问题!如有其他疑问,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值