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

在排序数组中查找元素的第一个和最后一个位置(二分查找进阶)

在写这个题目之前需要大家自行看一下我之前写的博客有关二分查找思想,如何判断什么时候使用二分查找以及边界值的确定:二分查找思想+力扣实例_徐憨憨!的博客-CSDN博客

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

题目链接:力扣

思路分析:

1. 题目给出了在有序数组中查找目标元素target下标的位置且要求时间复杂度是O(logn),此时想到的就是利用二分查找;

2.目标元素target可能存在于数组中也可能不存在于数组中,需要分情况讨论,可以分成target在数组的左边,在数组的右边,和数组的内部:

  • 情况一:target 在数组范围的右边或者左边,例如数组{3, 4, 5},target为2或者数组{3, 4, 5},target为6,此时应该返回{-1, -1}
  • 情况二:target 在数组范围中,且数组中不存在target,例如数组{3,6,7},target为5,此时应该返回{-1, -1}
  • 情况三:target 在数组范围中,且数组中存在target,例如数组{3,6,7},target为6,此时应该返回{1, 1}

3.当数组中有target这个元素时,需要分别求出target的左边界(即第一次出现的位置)和右边界(即最后一次出现的位置),又因为时间复杂度要求是O(logn),所以在找左右边界的时候依然采用二分查找的策略,只是判断条件和下标更新的时候需要稍作调整;

4.因为给出的区间是左闭右闭的,所以在while循环中的判断语句使用left <= right,当调出循环时,left一定大于right,所以得到的左右边界都是不包含target的.

寻找右边界:

 //找右边界值private int findRightBorder(int[] nums, int target) {int left = 0;int right = nums.length - 1;int rightBorder = -2; //如果返回的rightBorder为-2说明没有查找到右边界while (left <= right) {int mid= left + ((right - left) / 2);//防止数据溢出if (nums[mid] > target) {//此时说明右边界一定在mid的左边right = middle - 1;} else { //nums[mid]=target时,说明右边界>=mid//nums[mid<target时,说明右边界>midleft = mid+ 1;rightBorder = left;}}return rightBorder;}

寻找左边界:

//找左边界值private int findLeftBorder(int[] nums, int target) {int left = 0;int right = nums.length - 1;int leftBorder = -2;//如果返回-2,说明没有找到左边界值while (left <= right) {int middle = left + ((right - left) / 2);//防止数据溢出if (nums[middle] >= target) { //当nums[mid]=target时,说明左边界<=mid//当nums[mid]>target时,说明左边界<midright = middle - 1;leftBorder = right;} else {//当nus[mid]<target时,说明左边界>midleft = middle + 1;}}return leftBorder;}

主方法中:

public int[] searchRange(int[] nums, int target) {int leftBorder = findLeftBorder(nums, target);int rightBorder = findRightBorder(nums, target);//表示target在数组的左边和右边if (leftBorder == -2 || rightBorder == -2) return new int[]{-1, -1};//说明target在存在于数组内部if (rightBorder - leftBorder > 1) {//因为leftBorder和rightBorder都不包含边界值target//所以需要给leftBorder+1 rightBorder-1return new int[]{leftBorder + 1, rightBorder - 1};}return new int[]{-1, -1};}

完整代码如下:

class Solution {public int[] searchRange(int[] nums, int target) {int leftBorder = findLeftBorder(nums, target);int rightBorder = findRightBorder(nums, target);//表示target在数组的左边和右边if (leftBorder == -2 || rightBorder == -2) return new int[]{-1, -1};//说明target在存在于数组内部if (rightBorder - leftBorder > 1) {//因为leftBorder和rightBorder都不包含边界值target//所以需要给leftBorder+1 rightBorder-1return new int[]{leftBorder + 1, rightBorder - 1};}return new int[]{-1, -1};}//找右边界值private int findRightBorder(int[] nums, int target) {int left = 0;int right = nums.length - 1;int rightBorder = -2; while (left <= right) {int middle = left + ((right - left) / 2);if (nums[middle] > target) {right = middle - 1;} else { left = middle + 1;rightBorder = left;}}return rightBorder;}//找左边界值private int findLeftBorder(int[] nums, int target) {int left = 0;int right = nums.length - 1;int leftBorder = -2;while (left <= right) {int middle = left + ((right - left) / 2);if (nums[middle] >= target) { right = middle - 1;leftBorder = right;} else {left = middle + 1;}}return leftBorder;}}

http://www.lryc.cn/news/58617.html

相关文章:

  • 1 Nginx跨域配置
  • ChatGTP如此强大,我们普通人如何利用它来赚钱?
  • 常见的九种大数据分析模型
  • 射频识别(RFID)技术的基本原理、特性、发展和应用
  • 3.3 二维随机变量条件分布
  • Kafka——概述、安装及命令行操作
  • 怎么控制ERP企业管理系统开发的价格
  • 我在“Now In Android”中学到的 9 件事
  • ChatGPT宝藏插件丨装上之后,上网、语音聊天、一键分享对话……简直让你爽到起飞!
  • 私有句柄表
  • Vue——类与样式绑定
  • 软考中项计算题总结
  • 如何使用基于GPT-4的Cursor编辑器提升开发效率
  • 压箱底教程分享,手把手教会你如何注册target账号和下单
  • 一次性搞懂dBSPL、dBm、dBu、dBV、dBFS的区别!
  • 漂亮实用的15个脑图模板,你知道哪些是AI做的吗?
  • 历代程序员都无法逃脱的诅咒 -- 低代码
  • 14Exceptional Control Flow Exceptions and Process(异常控制流,异常和进程)
  • LeetCode - 两数之和
  • Python 小型项目大全 31~35
  • 他又赚了一万美金
  • 企业工程项目管理系统+spring cloud 系统管理+java 系统设置+二次开发
  • 教你使用Apache搭建Http
  • ZooKeeper+Kafka+ELK+Filebeat集群搭建实现大批量日志收集和展示
  • 数据结构初阶 - 总结
  • 代码随想录算法训练营第四十四天-动态规划6|518. 零钱兑换 II ,377. 组合总和 Ⅳ (遍历顺序决定是排列还是组合)
  • wma格式怎么转换mp3,4种方法超快学
  • 【数据结构与算法】判定给定的字符向量是否为回文算法
  • 考研数二第十七讲 反常积分与反常积分之欧拉-泊松(Euler-Poisson)积分
  • 【论文总结】理解和减轻IoT消息协议的安全风险