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

news2024/11/25 22:51:00

引言

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

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

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

基本代码

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:

输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]

示例 2:

输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]

示例 3:

输入:nums = [], target = 0
输出:[-1,-1]

提示:

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

代码实现及思路

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 的数组,用于存储目标值的左侧和右侧边界索引。

2. 处理特殊情况:

  • 如果数组长度为 0,直接返回 [-1, -1],因为空数组中不存在任何元素。
  • 如果数组长度为 1,检查数组中的唯一元素是否等于目标值。如果相等,返回 [0, 0];如果不相等,返回 [-1, -1]。

3. 寻找左侧边界:

  • 使用二分查找的变体来定位目标值的左侧边界。
  • 在 while 循环中,根据 nums[mid] 与 target 的比较结果,调整 left 或 right 的值。
  • 当 `left` 大于 right 时,循环结束,表示搜索区间为空,目标值不存在。
  • 在循环结束后,检查 left 是否在数组范围内,并且 nums[left] 是否等于目标值。如果是,arr[0] 赋值为 left,否则为 -1。

4. 重置变量并寻找右侧边界:

  • 将 right 初始化为数组的最后一个索引。
  • 再次使用二分查找的变体,但这次是为了找到目标值的右侧边界。
  • 调整 left 或 right 的值,使得 left 向右移动,right 向左移动,直到找到目标值的最后一个出现位置。
  • 在循环结束后,检查 right 是否在数组范围内,并且 nums[right] 是否等于目标值。如果是,arr[1] 赋值为 right,否则为 -1。

5. 返回结果:

  • 返回包含左侧和右侧边界索引的数组arr。
  • 这种方法确保了即使在目标值在数组中多次出现的情况下,也能正确地找到其首次和最后一次出现的索引。通过两次二分查找,分别从数组的两端向中间搜索,可以有效地定位目标值的边界。

结果展示

文末

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1494241.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++专栏】C++入门 | 命名空间、输入输出、缺省参数

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;C专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家 点赞&#x1f44d;收藏⭐评论✍ C入门 | 命名空间、输入输出、缺省参数 文章编号&#xff1a;C入门 / 0…

Java agent技术的注入利用与避坑点

什么是Java agent技术&#xff1f; Java代理&#xff08;Java agent&#xff09;是一种Java技术&#xff0c;它允许开发人员在运行时以某种方式修改或增强Java应用程序的行为。Java代理通过在Java虚拟机&#xff08;JVM&#xff09;启动时以"代理"&#xff08;agent…

react native中如何使用webView调用腾讯地图选点组件

react native中如何使用webView调用腾讯地图选点组件 效果示例图代码示例备注 效果示例图 代码示例 import React, {useEffect, useRef, useState} from react; import {Modal, StyleSheet} from react-native; import {pxToPd} from ../../common/js/device; import {WebView…

使用PDFBox封装一个简单易用的工具类快速生成pdf文件

文章目录 一、PDFbox说明1、坐标2、线3、图4、字5、字体加载6、jfreechart图表转字节数组7、依赖二、PDFbox样式1、文字颜色2、线颜色3、线样式三、工具类边框样式对齐样式表行列图片列pdf工具类测试方法四、效果图一、PDFbox说明 1、坐标 文档左下角为坐标原点,x轴向右从0增…

Cluade3干货:超越GPT,模型特点分析+使用教程|2024年3月更新

就在刚刚&#xff0c;Claude 发布了最新的大模型 Claude3&#xff0c;并且一次性发布了三个模型&#xff0c;分别是 Claude 3 Haiku&#xff1a;&#xff08;日本俳句 &#xff09;Claude 3 Sonnet&#xff08;英文十四行诗&#xff09;Claude 3 Opus&#xff08;古典乐作品集…

HarmonyOS NEXT应用开发案例——滑动页面信息隐藏与组件位移效果

介绍 在很多应用中&#xff0c;向上滑动"我的"页面&#xff0c;页面顶部会有如下变化效果&#xff1a;一部分信息逐渐隐藏&#xff0c;另一部分信息逐渐显示&#xff0c;同时一些组件会进行缩放或者位置移动。向下滑动时则相反。 效果图预览 使用说明 向上滑动页面…

Vue:双token无感刷新

文章目录 初次授权与发放Token&#xff1a;Access Token的作用&#xff1a;Refresh Token的作用&#xff1a;无感刷新&#xff1a;安全机制&#xff1a;后端创建nest项目AppController 添加login、refresh、getinfo接口创建user.dto.tsAppController添加模拟数据 前端Hbuilder创…

ARM中专用指令(异常向量表、异常源、异常返回等)

状态寄存器传送指令 CPSR寄存器 状态寄存器传送指令:访问&#xff08;读写&#xff09;CPSR寄存器 读CPSR MRS R1, CPSR R1 CPSR 写CPSR MSR CPSR, #0x10 0x10为User模式&#xff0c;且开启IRQ和FRQ CPSR 0x10 在USER模式下不能随意修改CPSR&#xff0c;因为USER模式…

js五星评价的制作方法

方法有两种&#xff0c;1、jquer插件&#xff1b;2、图片循环&#xff1b; 第一种、效果图 代码 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"…

机器学习---拉格朗日乘子法、Huber Loss、极大似然函数取对数的原因

1. 拉格朗日乘子法 拉格朗日乘子法&#xff08;Lagrange multipliers&#xff09;是一种寻找多元函数在一组约束下的极值的方法。通过引 入拉格朗日乘子&#xff0c;可将有d个变量与k个约束条件的最优化问题转化为具有d&#xff0b;k个变量的无约束优化 问题求解。本文希望通…

java工程师面试笔试题,阿里+头条+抖音+百度+蚂蚁+京东面经

前言 分布式事务主要解决分布式一致性的问题。说到底就是数据的分布式操作导致仅依靠本地事务无法保证原子性。与单机版的事务不同的是&#xff0c;单机是把多个命令打包成一个统一处理&#xff0c;分布式事务是将多个机器上执行的命令打包成一个命令统一处理。 MySQL 提供了…

软件测试计划包括哪些内容?专业第三方软件测试机构推荐

软件测试计划是为确保软件质量而制定的详细计划&#xff0c;它在软件开发周期中扮演着至关重要的角色。一个良好的软件测试计划可以确保软件在交付给最终用户之前经过全面的测试和验证&#xff0c;减少软件出现缺陷和问题的可能性。 软件测试计划一般包括以下内容&#xff1a;…

汇编程序中引用头文件

文章目录 写在前面x86汇编示例(AT&T风格ARM汇编示例运行结果 写在前面 汇编程序中也是可以使用头文件的&#xff0c;因为头文件实际上就是预处理中的一环&#xff0c;使用预处理器也对汇编程序中的头文件进行预处理 本文使用的汇编例程&#xff1a; x86版 AT&T汇编hel…

打印螺旋矩阵

打印螺旋矩阵 题目 如&#xff1a;输入 n 5&#xff1b; 输出&#xff1a; 1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9解题 这种规律打印题我个人感觉是真的不好写&#xff0c;一看答案感觉也就那回事&#xff0c;真自己琢磨&#xff0c;半…

15 实战:Kaggle房价预测 + 课程竞赛:加州2020年房价预测【李沐动手学深度学习课程笔记】

15 实战&#xff1a;Kaggle房价预测 课程竞赛&#xff1a;加州2020年房价预测【李沐动手学深度学习课程笔记】https://zhuanlan.zhihu.com/p/685343754 写在前面&#xff1a;这里格式很乱&#xff0c;代码直接去知乎copy 1 实战Kaggle比赛&#xff1a;预测房价 1.1 实现几个函…

flowable使用taskService.addComment新增评论需要full_msg字段进行读取

背景 在构建创业项目JeecgFlow过程中&#xff0c;在调用taskService.addComment接口出现了异常。就是数据存储的Message信息出现了截取&#xff0c;也就是存储不完整。 效果如下. flowable版本6.7.2 问题排查 接口详解及问题代码 //新增评论的接口说明 Comment addComment(…

华为OD机试“HJ5 进制转换”Java编程解答

描述 写出一个程序&#xff0c;接受一个十六进制的数&#xff0c;输出该数值的十进制表示。 数据范围&#xff1a;保证结果在 1≤n≤231−1 输入描述&#xff1a; 输入一个十六进制的数值字符串。 输出描述&#xff1a; 输出该数值的十进制字符串。不同组的测试用例用\…

OpenAI高管联名回击:马斯克曾提议并入特斯拉,认为OpenAI注定失败

丨划重点 ① OpenAI周二发文回应马斯克提起的诉讼&#xff0c;称对双方走到这一步感到很难过。 ② 这篇博文的作者包括了OpenAI五位高管&#xff0c;其中首席科学家苏茨凯弗已经久违露面。 ③ OpenAI证实&#xff0c;只从马斯克处获得不到4500万美元资金&#xff0c;其他支持者…

企业对接Walmart平台API流程 On-request Reports API(二)

对接On-request Reports API 1、对接指南1.1 报告生成时间1.2 报告保留期1.3 请求限制1.4 报告请求工作流如何申请报告第 1 步&#xff1a;申请取消报告第 2 步&#xff1a;获取报表可用性状态第 3 步&#xff1a;下载报告 URL 2、代码实现2.1、获取访问API的token2.2、构建公共…

【记录】IDA|IDA设置text view为默认,并解决IDA7.6打开新固件卡顿的问题

版本&#xff1a;IDA Pro 7.6 Graph View&#xff08;控制流视图&#xff09;其实我真的看得很少&#xff0c;因为遇到分析难题时总是是因为间接调用&#xff0c;它根本分析不出来。但是一开IDA它就自动分析这个特别卡。所以今天想彻底解决一下&#xff0c;让默认打开为Text V…