刷题之Leetcode34题(超级详细)

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

力扣链接(opens new window)icon-default.png?t=N7T8https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/

给定一个按照升序排列的整数数组 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]

思路

这道题目如果基础不是很好,不建议大家看简短的代码,简短的代码隐藏了太多逻辑,结果就是稀里糊涂把题AC了,但是没有想清楚具体细节!

对二分还不了解的兄弟先做这两题:

  • 704.二分查找(opens new window)icon-default.png?t=N7T8https://programmercarl.com/0704.%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE.html
  • 35.搜索插入位置(opens new window)icon-default.png?t=N7T8https://programmercarl.com/0035.%E6%90%9C%E7%B4%A2%E6%8F%92%E5%85%A5%E4%BD%8D%E7%BD%AE.html

下面我来把所有情况都讨论一下。

寻找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}

这三种情况都考虑到,说明就想的很清楚了。

接下来,在去寻找左边界,和右边界了。

采用二分法来去寻找左右边界,为了让代码清晰,我分别写两个二分来寻找左边界和右边界。

刚刚接触二分搜索的兄弟不建议上来就想用一个二分来查找左右边界,很容易把自己绕进去,建议扎扎实实的写两个二分分别找左边界和右边界

寻找右边界

先来寻找右边界,至于二分查找,如果看过刷题之Leetcode704题(超级详细)-CSDN博客就会知道,二分查找中什么时候用while (left <= right),有什么时候用while (left < right),其实只要清楚循环不变量,很容易区分两种写法。

那么这里我采用while (left <= right)的写法,区间定义为[left, right],即左闭右闭的区间(如果这里有点看不懂了,强烈建议把刷题之Leetcode704题(超级详细)-CSDN博客这篇文章先看了,704题目做了之后再做这道题目就好很多了)

确定好:计算出来的右边界是不包含target的右边界,左边界同理。

可以写出如下代码

 int getRightBorder(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        int rightBorder = -2; // 记录一下rightBorder没有被赋值的情况
        while (left <= right) {
            int middle = left + ((right - left) / 2);
            if (nums[middle]==target) {// 寻找右边界,nums[middle] == target的时候更新left
                left = middle + 1;
                rightBorder = left;
                
            } else if(nums[middle]>target){ 
                right = middle - 1;
            }else{
                left=middle-1;
}
        }
        return rightBorder;
    }

寻找左边界

 int getLeftBorder(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        int leftBorder = -2; // 记录一下leftBorder没有被赋值的情况
        while (left <= right) {
            int middle = left + ((right - left) / 2);
            if (nums[middle] == target) { // 寻找左边界,nums[middle] == target的时候更新right
                right = middle - 1;
                leftBorder = right;
            } else if(nums[middle]>target){
                right=middle-1;
            }else{ 
                left=middle+1;
}
        }
        return leftBorder;
    }

处理三种情况

左右边界计算完之后,看一下主体代码,这里把上面讨论的三种情况,都覆盖了

class Solution {
    int[] searchRange(int[] nums, int target) {
        int leftBorder = getLeftBorder(nums, target);
        int rightBorder = getRightBorder(nums, target);
        // 情况一
        if (leftBorder == -2 || rightBorder == -2) return new int[]{-1, -1};
        // 情况三
        if (rightBorder - leftBorder > 1) return new int[]{leftBorder + 1, rightBorder - 1};
        // 情况二
        return new int[]{-1, -1};
    }

 int getRightBorder(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        int rightBorder = -2; // 记录一下rightBorder没有被赋值的情况
        while (left <= right) {
            int middle = left + ((right - left) / 2);
            if (nums[middle]==target) {// 寻找右边界,nums[middle] == target的时候更新left
                left = middle + 1;
                rightBorder = left;
                
            } else if(nums[middle]>target){ 
                right = middle - 1;
            }else{
                 left=middle+1;
}
        }
        return rightBorder;
    }
    int getLeftBorder(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        int leftBorder = -2; // 记录一下leftBorder没有被赋值的情况
        while (left <= right) {
            int middle = left + ((right - left) / 2);
            if (nums[middle] == target) { // 寻找左边界,nums[middle] == target的时候更新right
                right = middle - 1;
                leftBorder = right;
            } else if(nums[middle]>target){
                right=middle-1;
            }else{ 
                left=middle+1;
}
        }
        return leftBorder;
    }

这份代码在简洁性很有大的优化空间,例如把寻找左右区间函数合并一起。

但拆开更清晰一些,而且把三种情况以及对应的处理逻辑完整的展现出来了。

总结

初学者建议大家一块一块的去分拆这道题目,正如本题解描述,想清楚三种情况之后,先专注于寻找右区间,然后专注于寻找左区间,左右根据左右区间做最后判断。

不要上来就想如果一起寻找左右区间,搞着搞着就会顾此失彼,绕进去拔不出来了。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Jenkins 安装部署

1、安装下载 官网地址&#xff1a;Jenkins 下载 war 包 1、前置环境 JDK 环境&#xff08;根据 Jenkins 版本不同&#xff0c;需要的 JDK 版本不同&#xff0c;目前需要 JDK11 的版本来支持&#xff09;Maven maven 官网下载压缩包 &#xff0c;并将其传输到服务器&#xf…

【Python】免费的图片/图标网站

专栏文章索引&#xff1a;Python 有问题可私聊&#xff1a;QQ&#xff1a;3375119339 这里是我收集的几个免费的图片/图标网站&#xff1a; iconfont-阿里巴巴矢量图标库icon&#xff08;.ico&#xff09;INCONFINDER&#xff08;.ico&#xff09;

clickhouse MPPDB数据库--新特性使用示例

clickhouse 新特性&#xff1a; 从clickhouse 22.3至最新的版本24.3.2.23&#xff0c;clickhouse在快速发展中&#xff0c;每个版本都增加了一些新的特性&#xff0c;在数据写入、查询方面都有性能加速。 本文根据clickhouse blog中的clickhouse release blog中&#xff0c;学…

【C++入门】关键字、命名空间以及输入输出

&#x1f49e;&#x1f49e; 前言 hello hello~ &#xff0c;这里是大耳朵土土垚~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#x…

基于Python近红外光谱分析与机器学、深度学习方法融合技术应用

郁磊副教授&#xff0c;主要从事MATLAB 编程、机器学习与数据挖掘、数据可视化和软件开发、人工智能近红外光谱分析、生物医学系统建模与仿真&#xff0c;具有丰富的实战应用经验&#xff0c;主编《MATLAB智能算法30个案例分析》、《MATLAB神经网络43个案例分析》相关著作。已发…

6:算法基础--6.1:线性结构 ,6.2:查找算法

转上一节&#xff1a; http://t.csdnimg.cn/ql5Cdhttp://t.csdnimg.cn/ql5Cd 课程内容提要&#xff1a; 6&#xff1a;知识点考点详解 6.1&#xff1a;线性结构 通常分析时间复杂度的方法是从算法中选取-种对于所研究的问题来说是基本运算的操作&#xff0c;以 该操作重…

51单片机入门:认识开发板

认识开发板 板载资源&#xff1a; 数码管模块 说明&#xff1a; 2个四位一体共阴数码管 详细&#xff1a; 2个四位一体&#xff1a;两个独立的四位数码管&#xff0c;每个四位数码管都是“一体”的设计&#xff0c;也就是说&#xff0c;每个数码管内部集成了四个独立的七段LE…

【Linux】Ubuntu 磁盘管理

准备一个U盘或者SD卡&#xff08;含读卡器&#xff09;&#xff0c;并将其格式化成 FAT32 格式&#xff0c;不要使用NTFS格式&#xff08;这是微软的专利&#xff0c;大部分Linux系统不支持&#xff09;和exFAT格式&#xff08;有的Linux系统也不支持&#xff09;。 如果Ubun…

Lafida多目数据集实测

Lafida 数据集 paper&#xff1a;J. Imaging | Free Full-Text | LaFiDa—A Laserscanner Multi-Fisheye Camera Dataset 官网数据&#xff1a;https://www.ipf.kit.edu/english/projekt_cv_szenen.php 官网&#xff1a;KIT-IPF-Software and Datasets - LaFiDa 标定数据下载&…

【蓝桥杯嵌入式】9届程序题刷题记录及反思

一、题目内容分析 二、LCD单字符高亮显示实现 本次要求显示两个字符&#xff0c;此函数高亮pos及它后面一个字符 void highlight(uint8_t *str,uint8_t pos) {int i 0;for(i 0; i < 20; i){if(i ! pos && i! (pos1))LCD_DisplayChar(Line3,(320 - (16 * i)),st…

Python输出不了中文怎么解决

在文件头加上#encoding&#xff1a;utf-8即可。 # encoding: utf-8 print helloworld print u"学习" print (unicode("学习", encoding"utf-8")) shell输出&#xff1a; helloworld 学习 学习 还可以用#-*- coding: UTF-8 -*- 来指定。

LangChain学习笔记—RAG(检索增强生成)

LangChain LangChain是一个软件开发框架&#xff0c;可以更轻松地使用大型语言模型&#xff08;LLM&#xff09;创建应用程序。它是一个具有 Python 和 JavaScript 代码库的开源工具。LangChain 允许开发人员将 GPT-4 等 LLM 与外部数据相结合&#xff0c;为聊天机器人、代码理…

C++ | Leetcode C++题解之第10题正则表达式匹配

题目&#xff1a; 题解&#xff1a; class Solution { public:bool isMatch(string s, string p) {int m s.size();int n p.size();auto matches [&](int i, int j) {if (i 0) {return false;}if (p[j - 1] .) {return true;}return s[i - 1] p[j - 1];};vector<…

WGCAT工单系统使用指南 - 工单有哪几种状态

WGCAT工单管理系统设计的工单生命周期比较简单易懂 1、待接收 2、处理中 3、已拒绝 4、已完成 5、已关闭

CYP450综述-20年-地表最强系列-文献精读-4

Discovery and modification of cytochrome P450 for plant natural products biosynthesis 发现与改造细胞色素P450以合成植物天然产品 一篇关于植物CYP450的综述&#xff0c;地表最强&#xff0c;总结的最全面的版本之一&#xff0c;各位看官有推荐请留言评论区~ Discovery…

App.vue触发axios报错及解决方案

App.vue触发axios报错及解决方案 修改根目录下vue.config.js文件 module.exports {publicPath: ./,assetsDir: assets,configureWebpack: {devServer: {client: {overlay: false}}} }重新npm run dev 搞定

python作业

1.找出10000以内能被5或6整除&#xff0c;但不能被两者同时整除的数(函数) 2.写一个方法&#xff0c;计算列表所有偶数下标元素的和(注意返回值) 3.根据完整的路径从路径中分离文件路径、文件名及扩展名。 4.根据标点符号对字符串进行分行 5.去掉字符串数组中每个字符串的空格 …

波奇学Linux:

面向数据报&#xff1a;udp没有发送缓冲区&#xff0c;发送几次数据报&#xff0c;读取几次数据报&#xff0c;write和read一一对应 tcp通信时只管识别数据&#xff0c;在应用层才对字节进行拼接分析&#xff0c;得到完整请求 简单来说&#xff1a;udp之间传递的是报文&#x…

【打印SQL执行日志】⭐️Mybatis-Plus通过配置在控制台打印执行日志

目录 前言 一、Mybatis-Plus 开启日志的方式 二、测试 三、日志分析 章末 前言 小伙伴们大家好&#xff0c;相信大家平时在处理问题时都有各自的方式&#xff0c;最常用以及最好用的感觉还是断点调试&#xff0c;但是涉及到操作数据库的执行时&#xff0c;默认的话在控制台…

Excel、PowerQuery 和 ChatGPT 终极手册(上)

原文&#xff1a;Ultimate ChatGPT Handbook for Enterprises 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 序言 在不断发展的数据管理和分析领域中&#xff0c;掌握 Excel 的查找功能不仅是一种技能&#xff0c;更是高效数据处理的基石。《使用 Power Query 和 Ch…