备战蓝桥杯————二分查找(二)

引言

在上一篇博客中,我们深入探讨了二分搜索算法及其在寻找数组左侧边界的应用。二分搜索作为一种高效的查找方法,其核心思想在于通过不断缩小搜索范围来定位目标值。在本文中,我们将继续这一主题,不仅会回顾二分搜索的基本原理,还将重点介绍如何利用这一算法来寻找数组中目标值的右侧边界。通过对比左侧和右侧边界的搜索,我们将揭示二分搜索算法的灵活性和强大功能。无论您是在准备技术面试,还是在日常编程中寻求效率提升,本文都将为您提供宝贵的洞见。

一、寻找右侧边界的二分查找

在有序数组中寻找特定值的右侧边界是二分查找算法的一个重要变体。与寻找左侧边界类似,我们可以通过调整搜索区间的边界来实现。本文将介绍两种写法:左闭右开的常见写法和两端都闭的统一写法。

基本代码

java 复制代码
int right_bound(int[] nums, int target) {
    int left = 0, right = nums.length;
    
    while (left < right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) {
            left = mid + 1; // 注意
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid;
        }
    }
    return left - 1; // 注意
}

代码解释

1. 为什么这个算法能够找到右侧边界?

答:关键在于当 nums[mid] == target 时,我们不立即返回,而是通过 left = mid + 1 增大搜索区间的左边界,从而锁定右侧边界。

2. 为什么最后返回 left - 1 而不是 left

答:由于循环终止时 leftright 相等,而我们希望返回的是目标值的右侧边界,所以需要返回 left - 1。这样,当 left 等于数组长度时,表示目标值不存在,返回 -1

3. 如何处理目标值不存在的情况?

答:在循环结束后,我们检查 nums[left - 1] 是否等于目标值。如果不等于,或者 left - 1 索引越界,说明目标值不存在,返回 -1

二、在排序数组中查找元素的第一个跟最后一个

题目描述

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值 target,返回 [-1, -1]。你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

示例 1:

ini 复制代码
输入: nums = [5,7,7,8,8,10], target = 8
输出: [3,4]

示例 2:

ini 复制代码
输入: nums = [5,7,7,8,8,10], target = 6
输出: [-1,-1]

示例 3:

ini 复制代码
输入: nums = [], target = 0
输出: [-1,-1]

提示:

  • 0 <= nums.length <= 105
  • -109 <= nums[i] <= 109
  • nums 是一个非递减数组
  • -109 <= target <= 109

代码实现及思路

java 复制代码
class Solution {
    public int[] searchRange(int[] nums, int target) {
        int left=0,right=nums.length-1;
        int[] arr = new int[2];
        if(nums.length==0)return new int[]{-1,-1};
        if(nums.length==1 && nums[0]==target)return new int[]{0,0};
        if(nums.length==1 && nums[0]!=target)return new int[]{-1,-1};
        while(left<=right){
            int mid=left+(right-left)/2;
            if(nums[mid]>=target)right=mid-1;
            if(nums[mid]<target)left=mid+1;
        }
        if(left<nums.length)arr[0]= nums[left]==target?  left:-1;
        else arr[0]=-1;
        right=nums.length-1;
        while(left<=right){
            int mid=left+(right-left)/2;
            if(nums[mid]<=target)left=mid+1;
            if(nums[mid]>target)right=mid-1;
        }
        if(right>=0)arr[1]= nums[right]==target? right:-1;
        else arr[1]=-1;
        return arr;
    }
}

这段代码实现了一个名为 searchRange 的方法,它用于在一个有序数组 nums 中查找给定目标值 target 的第一个和最后一个出现的索引。该方法返回一个包含两个元素的数组,第一个元素是目标值的最小索引(左侧边界),第二个元素是最大索引(右侧边界)。如果目标值不存在于数组中,则两个元素都为 -1。

以下是该方法的思路:

  1. 初始化变量:
  • left 和 right 分别初始化为数组的起始索引和结束索引。
  • arr 是一个长度为 2 的数组,用于存储目标值的左侧和右侧边界索引。
  1. 处理特殊情况:
  • 如果数组长度为 0,直接返回 [-1, -1],因为空数组中不存在任何元素。
  • 如果数组长度为 1,检查数组中的唯一元素是否等于目标值。如果相等,返回 [0, 0];如果不相等,返回 [-1, -1]。
  1. 寻找左侧边界:
  • 使用二分查找的变体来定位目标值的左侧边界。
  • 在 while 循环中,根据 nums[mid] 与 target 的比较结果,调整 left 或 right 的值。
  • 当 `left` 大于 right 时,循环结束,表示搜索区间为空,目标值不存在。
  • 在循环结束后,检查 left 是否在数组范围内,并且 nums[left] 是否等于目标值。如果是,arr[0] 赋值为 left,否则为 -1。
  1. 重置变量并寻找右侧边界:
  • 将 right 初始化为数组的最后一个索引。
  • 再次使用二分查找的变体,但这次是为了找到目标值的右侧边界。
  • 调整 left 或 right 的值,使得 left 向右移动,right 向左移动,直到找到目标值的最后一个出现位置。
  • 在循环结束后,检查 right 是否在数组范围内,并且 nums[right] 是否等于目标值。如果是,arr[1] 赋值为 right,否则为 -1。
  1. 返回结果:
  • 返回包含左侧和右侧边界索引的数组arr。
  • 这种方法确保了即使在目标值在数组中多次出现的情况下,也能正确地找到其首次和最后一次出现的索引。通过两次二分查找,分别从数组的两端向中间搜索,可以有效地定位目标值的边界。

结果展示

文末

通过本文的讨论,我们不仅复习了二分搜索的基本概念,还学习了如何扩展这一算法来寻找数组中元素的左侧和右侧边界。这些技巧不仅在解决特定编程问题时非常有用,也体现了算法思维在优化问题解决过程中的重要性。二分搜索算法的变体和应用广泛,从简单的查找问题到复杂的数据结构操作,都可以看到它的身影。希望本文能够帮助您更好地理解和运用二分搜索,提升您的编程技能。感谢您的阅读,期待在下一篇文章中与您再次相遇

相关推荐
TN_stark93210 分钟前
多进程/线程并发服务器
服务器·算法·php
汉克老师35 分钟前
GESP4级考试语法知识(贪心算法(四))
开发语言·c++·算法·贪心算法·图论·1024程序员节
smj2302_796826521 小时前
用枚举算法解决LeetCode第3348题最小可整除数位乘积II
python·算法·leetcode
爱吃生蚝的于勒1 小时前
C语言最简单的扫雷实现(解析加原码)
c语言·开发语言·学习·计算机网络·算法·游戏程序·关卡设计
秋说2 小时前
【数据结构 | C++】整型关键字的平方探测法散列
数据结构·c++·算法
weixin_478689762 小时前
【回溯法】——组合总数
数据结构·python·算法
戊子仲秋3 小时前
【LeetCode】每日一题 2024_11_14 统计好节点的数目(图/树的 DFS)
算法·leetcode·深度优先
TaoYuan__4 小时前
机器学习的常用算法
人工智能·算法·机器学习
用户40547878374825 小时前
深度学习笔记 - 使用YOLOv5中的c3模块进行天气识别
算法
十七算法实验室5 小时前
Matlab实现麻雀优化算法优化随机森林算法模型 (SSA-RF)(附源码)
算法·决策树·随机森林·机器学习·支持向量机·matlab·启发式算法