当前位置: 首页 > news >正文

在排序数组中查找元素的第一个和最后一个位置

目录

一:题目链接

二:题目思路

三:代码实现


一:题目链接

        题目给出的非递减顺序排列的数组,指的是整段数组要么是全部递增,或者整段数组元素大小不变,或者整段数组递增和元素大小不变区间交替。并且题目要求使用的算法时间复杂度是O(log n),所以目前我们只能使用 二分查找 算法了。

二:题目思路

        首先,我们知道,二分查找算法 有 循环条件判断条件,并且解题时我们能把数组分段来解决问题,那么就基本可以使用二分查找算法了。

        目前我们使用二分查找算法  循环条件 和 判断条件 只能找到精确的一个确定值,但是这道题结果是一个区间,所以,我们要找到左端点右端点,那么,判断条件应该怎么改?如图:

        首先,我们要找到左端点,取到 left 和 right 中点的 mid 有两种情况,可以把数组分为上图的两段。

        当 mid < target 时,证明 mid 左边一段都是 小于 target 的,那么 left 可以更新成 mid + 1。

        当 mid >= target 时,证明 mid 右边的一段是 大于或等于 target 的,此时,把 right 更新成 mid 位置,为什么 right 不更新成 mid - 1,如果 mid 的位置的值刚好是 target 起始端点,那么 right 更新成 mid - 1就会出现 left 和 right 包含的区间都是小于 target ,后续都是错误了。

        找右端点同理,取到 left 和 right 中点的 mid 有两种情况,可以把数组分为下图的两段。

         当 mid > target 时,证明 mid 右边一段都是 大于 target 的,那么 right 可以更新成 mid - 1了。

        当 mid <= target 时,证明 mid 左边的一段是 小于或等于 target 的,此时,把 left 更新成 mid 位置,为什么 left 不更新成 mid + 1,如果 mid 的位置的值刚好是 target 结束端点,那么 left 更新成 mid + 1就会出现 left 和 right 包含的区间都是大于 target ,后续都是错误了。

解决完判断条件,那么整个判断应该在什么样的循环条件下进行?

        我们想到的肯定是 left < right ,这种循环条件一定是正确的,要不要加上 == 变成 left <= right ?我们来判断一下,如果 left == right 是什么情况?肯定是找到了当前的端点了,就可以直接返回了,如果继续循环一次,进入的是 right = mid 或者 left = mid 的判断条件,就会进入死循环了。所以,正确循环条件是 left < right 。

三:代码实现

        int[] arr = new int[2];arr[0] = -1;arr[1] = -1;//如果数组为空,直接返回if(nums.length == 0) {return arr;}//寻找左端点int left = 0;int right = nums.length - 1;while(left < right) {int mid = left + (right - left) / 2;if(nums[mid] < target) {left = mid + 1;}else {right = mid;}}//判断是否有结果if(nums[left] != target) {return arr;}arr[0] = left;//寻找右端点left = 0;right = nums.length - 1;while(left < right) {int mid = left + (right -left + 1) / 2;if(nums[mid] > target) {right = mid - 1;}else {left = mid;}}arr[1] = left;return arr;

     int mid = left + (right -left + 1) / 2;为什么找中点时里面要加一,如图:

        

        如果 target 是 7 ,我们要找右端点时,正常来说如果代码不加一 计算的 mid 是第一个 7, 加一之后 计算的 mid 就可以取到 第二个 7 ,也就是得到右端点了。

http://www.dtcms.com/a/391949.html

相关文章:

  • 一条命令在ubuntu安装vscode
  • 【开题答辩全过程】以 ASP.NET抗疫物资管理系统为例,包含答辩的问题和答案
  • 探饭 - 字节跳动推出的AI美食推荐助手
  • ZCC5515_耐压9.5V ,超低静态功耗5uA,完全替代CS5515
  • 端脑云AI生图体验:从提示词到精美肖像
  • 临界处有一条看不见的河
  • JavaWeb--day8-- Mybatis(正式)
  • 基于WSL BES2710编译环境搭建方法
  • 模块化设计逻辑:太阳镜气流单元 / 耳机可拆卸结构的装配精度与兼容性分析
  • 半监督学习实战:如何用少量标注数据获得媲美全监督学习的性能?
  • 作业3(初学CSS)
  • CSS基础(总结)
  • 【信创云架构 PACS系统】全网首发-基于JDK17+Vue3全新开发的信创国产化系统
  • 若依vue项目里面,使用到oss,这个 是什么
  • Linux中的Ubuntu系统安装配置 MATLAB 开发环境、离线安装非root安装vscode
  • 网站单页应用(SPA)和多页应用(MPA)的区别
  • 10cm钢板矫平机:一副“钢铁脊椎”的矫正日记
  • Nano Banana (Gemini 2.5 Flash Image) 完整体验教程:一键生成你的专属 3D AI 手办
  • Qt水平布局:深入解析与优化技巧
  • 【vLLM 学习】Multilora Inference
  • 【硬件-笔试面试题-102】硬件/电子工程师,笔试面试题(知识点:RC滤波器的参数怎么计算)
  • 整体设计 语言拼凑/逻辑拆解/词典缝合 之 2 逻辑拆解(“你”) 决定逻辑描述列项的非真“自由”:自由选择/自由创新/自由意志(豆包助手)
  • 前端性能优化实用方案(四):DOM批处理减少80%重排重绘
  • 速通ACM省铜第九天 赋源码(Divine Tree)
  • win10程序(七)暴力xls转xlsx程序
  • PINN物理信息神经网络驱动的Burgers偏微分方程求解MATLAB代码
  • Linux系统多线程的同步问题
  • Anaconda下载及使用详细教程
  • 第二部分:VTK核心类详解(第43章 vtkCharArray字符数组类)
  • 2025年9月19日NSSCTF之[陇剑杯 2021]日志分析(问1)