【唐叔学算法】第九天:二分查找-高效搜索的秘诀

大家好,我是唐叔。今天我们要探讨的是一个非常经典且高效的算法——二分查找(Binary Search)。二分查找以其简洁而优雅的方式解决了在有序数组中快速定位元素的问题,并广泛应用于各种场景。本文将带你深入了解二分查找的概念、应用场景以及如何通过几个具体的LeetCode题目来实践这一技巧。

什么是二分查找?

基本概念

二分查找是一种在有序数组中查找特定元素的搜索算法。其工作原理是每次迭代都将搜索范围缩小一半,直到找到目标值或确定目标不存在为止。这种“折半”的特性使得二分查找的时间复杂度为 O(log n),非常适合处理大规模数据集。

工作流程

  1. 确定中间位置 mid
  2. 比较中间位置的值与目标值:
    • 如果相等,则找到了目标;
    • 如果中间位置的值大于目标值,则在左半部分继续查找;
    • 否则,在右半部分继续查找。
  3. 重复上述步骤直到找到目标或者搜索区间为空。

应用场景

  • 数据库索引:提高数据检索速度。
  • 排序后的数组搜索:如电话簿中的姓名查找。
  • 解决其他问题的基础:许多高级算法和数据结构都基于二分查找的思想。

实现细节

  • 边界条件:确保循环条件正确设置,避免无限循环。
  • 整数溢出:计算中间点时要注意防止整数溢出,通常使用 (low + high) / 2 可能导致溢出,可以改用 low + (high - low) / 2
  • 返回值:根据具体需求决定返回确切位置还是插入位置。

注意事项

  • 数组必须已排序:这是二分查找的前提条件。
  • 处理重复元素:如果数组中有重复元素,可能需要额外逻辑来处理边界情况。

实战解析

入门题:704. 二分查找

题目链接:704. 二分查找

题目描述:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

解题思路

直接应用标准的二分查找方法即可。首先初始化左右指针 leftright,然后进入循环比较中间值与目标值,根据比较结果调整指针位置。

Java代码实现
public int search(int[] nums, int target) {
    int left = 0;
    int right = nums.length - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2; // 防止溢出
        if (nums[mid] == target) {
            return mid;
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return -1;
}

中等题:34. 在排序数组中查找元素的第一个和最后一个位置

题目链接:34. 在排序数组中查找元素的第一个和最后一个位置

题目描述:给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值 target,返回 [-1, -1]。

解题思路

这个问题可以通过两次二分查找来解决:一次找第一个出现的位置,另一次找最后一个出现的位置。关键在于当找到目标值后不要立即返回,而是继续搜索以确认是否为边界位置。

Java代码实现
public int[] searchRange(int[] nums, int target) {
    int[] result = new int[]{-1, -1};
    result[0] = findFirst(nums, target);
    result[1] = findLast(nums, target);
    return result;
}

private int findFirst(int[] nums, int target) {
    int index = -1;
    int start = 0;
    int end = nums.length - 1;
    while (start <= end) {
        int mid = start + (end - start) / 2;
        if (nums[mid] >= target) {
            end = mid - 1;
        } else {
            start = mid + 1;
        }
        if (nums[mid] == target) index = mid;
    }
    return index;
}

private int findLast(int[] nums, int target) {
    int index = -1;
    int start = 0;
    int end = nums.length - 1;
    while (start <= end) {
        int mid = start + (end - start) / 2;
        if (nums[mid] <= target) {
            start = mid + 1;
        } else {
            end = mid - 1;
        }
        if (nums[mid] == target) index = mid;
    }
    return index;
}

更多LeetCode题目推荐

总结

通过今天的分享,相信大家已经了解了二分查找的基本原理及其在实际问题中的应用。二分查找是一个强大的工具,能够帮助我们高效地解决多种类型的搜索问题。希望各位读者朋友能够在实践中灵活运用这些知识,解决更多的编程挑战。

如果你有任何问题或想法,欢迎在评论区与我交流。让我们一起享受编程的乐趣,不断探索和学习!如果喜欢这篇文章,也别忘了点赞和分享哦!😊

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值