LeedCode刷题---二分查找类问题

顾得泉:个人主页

个人专栏:《Linux操作系统》  《C/C++》  《LeedCode刷题》

键盘敲烂,年薪百万!


一、二分查找

题目链接:二分查找

题目描述

       给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1
示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4

示例 2:

输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1

提示:

  1. 你可以假设 nums 中的所有元素是不重复的。
  2. n 将在 [1, 10000]之间。
  3. nums 的每个元素都将在 [-9999, 9999]之间。

解法

a.定义left,right指针,分别指向数组的左右区间。

b.找到待查找区间的中间点mid,找到之后分三种情况讨论:

       i. arr[mid] == target说明正好找到,返回mid的值;

       ii. arr[mid] > target说明[mid,right]这段区间都是大于target的,因此舍去右边区间,在左边[left, mid -1]的区间继续查找,即让right = mid -1,然后重复2过程;

       iii. arr[mid] < target说明[left,mid]这段区间的值都是小于target的,因此舍去左边区间,在右边[mid + 1,right]区间继续查找,即让left = mid +1,然后重复2过程;

c. 当left与right错开时,说明整个区间都没有这个数,返回-1

代码实现

int search(int* nums, int numsSize, int target) 
{int left = 0, right = numsSize - 1;while (left <= right){int mid = left + (right - left) / 2;if (nums[mid] == target) return mid;else if (nums[mid] > target)right = mid - 1;else left = mid + 1;}return -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

解法

算法思路:

       用的还是二分思想,就是根据数据的性质,在某种判断条件下将区间一分为二,然后舍去其中一个区间,然后再另一个区间内查找

       方便叙述,用×表示该元素resLeft表示左边界,resRight表示右边界。

寻找左边界思路:

 寻找左边界:

       我们注意到以左边界划分的两个区间的特点:

       ·左边区间[left, resLeft - 1]都是小于×的;

       ·右边区间(包括左边界)[resLeft,right]都是大于等于x的;因此,关于mid的落点,我们可以分为下面两种情况:

       当我们的mid落在[left,resLeft - 1]区间的时候,也就是arr[mid]<target。说明[left, mid]都是可以舍去的,此时更新left到mid + 1的位置,继续在[mid + 1, right]上寻找左边界;

       当mid落在[resLeft,right]的区间的时候,也就是arr[mid] >= targeto说明[mid + 1,right](因为mid可能是最终结果,不能舍去)是可以舍去的,此时更新right到mid的位置,继续在[left,mid]上寻找左边界;

       由此,就可以通过二分,来快速寻找左边界;

注意:

这里找中间元素需要向下取整。因为后续移动左右指针的时候:

       ·左指针:left = mid + 1,是会向后移动的,因此区间是会缩小的;

       ·右指针: right = mid ,可能会原地踏步(比如:如果向上取整的话,如果剩下1,2两个元素,left == 1,right == 2,mid == 2。更新区间之后,left,right,mid 的值没有改变,就会陷入死循环)。

       因此一定要注意,当right = mid的时候,要向下取整。

寻找右边界思路:

       寻右左边界:

       用resRight表示右边界;。我们注意到右边界的特点:

       左边区间 (包括右边界)[left,resRight]都是小于等于的;右边区间[resRight+ 1,right]都是大于)的;

       因此,关于mid的落点,我们可以分为下面两种情况:

       当我们的mid落在[left , resRight了区间的时候,说明[left,mid - 1]( mid不可以舍去,因为有可能是最终结果)都是可以舍去的,此时更新left到mid的位置。

       当mid 落在[resRghet ti, right]的区间的时候,说明[mid,right]内的元素是可以舍去的,此时更新ight到mid - 1的位置;

       由此,就可以通过二分,来快速寻找右边界

注意:

       这里找中间元素需要向上取整。因为后续移动左右指针的时候:

       ·左指针: left = mid,可能会原地踏步(比如:如果向下取整的话,如果剩下1,2两个元
素,left == 1, right == 2, mid == 1。更新区间之后,left,right, mid的值没有改变,就会陷入死循环)。

       ·右指针: right = mid - 1,是会向前移动的,因此区间是会缩小的;因此一定要注意,当right = mid的时候,要向下取整。

二分查找算法总结:

       请大家一定不要觉得背下模板就能解决所有二分问题。二分问题最重要的就是要分析题意,然后确定要搜索的区间,根据分析问题来写出二分查找算法的代码。

       要分析题意,确定搜索区间,不要死记模板,不要看左闭右开什么乱七八糟的题解要分析意,确定搜索区间,不要死记模板,不要看左闭右开什么乱七八糟的题解要分析题意,确定搜索区间,不要死记模板,不要看左闭右开什么乱七八糟的题解重要的事情说三遍。

模板记忆技巧:

       1.关于什么时候用三段式,还是二段式中的某一个,一定不要强行去用,而是通过具体的问题分析情况,根据查找区间的变化确定指针的转移过程,从而选择一个模板。

       2.当选择两段式的模板时:在求mid的时候,只有right - 1的情况下,才会向上取整(也就是+i取中间数)

代码实现

class Solution 
{
public:vector<int> searchRange(vector<int>& nums, int target) {if(nums.size() == 0) return {-1, -1};      int begin = 0;int left = 0, right = nums.size() - 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 {-1, -1};else begin = left; left = 0, right = nums.size() - 1;while(left < right){int mid = left + (right - left + 1) / 2;if(nums[mid] <= target) left = mid;else right = mid - 1;}return {begin, right};}
};

三、搜索插入位置

题目链接:搜索插入位置

题目描述

       给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

       请必须使用时间复杂度为 O(log n) 的算法。

示例 1:

输入: nums = [1,3,5,6], target = 5
输出: 2

示例 2:

输入: nums = [1,3,5,6], target = 2
输出: 1

示例 3:

输入: nums = [1,3,5,6], target = 7
输出: 4

提示:

  • 1 <= nums.length <= 104
  • -104 <= nums[i] <= 104
  • nums 为 无重复元素 的 升序 排列数组
  • -104 <= target <= 104

解法

算法思路:

a.分析插入位置左右两侧区间上元素的特点:

       设插入位置的坐标为index,根据插入位置的特点可以知道:

       [left,index - 1]内的所有元素均是小于target的;[index,right]内的所有元素均是大于等于target的。

b.设left为本轮查询的左边界,right为本轮查询的右边界。

       根据mid位置元素的信息,分析下一轮查询的区间:

        ·当nums [mid] >= target时,说明mid落在了[index,right]区间上,mid左边包括mid本身,可能是最终结果,所以我们接下来查找的区间在[left,mid]上。因此,更新right到mid位置,继续查找。

       ·当nums [mid] < target时,说明mid落在了[left,inde- 1]区间上,mid右边但不包括mid本身,可能是最终结果,所以我们接下来查找的区间在[mid+ 1, right]上。因此,更新left到mid + 1的位置,继续查找。

c.直到我们的查找区间的长度变为1,也就是(left == right的时候,left或者right所在的位置就是我们要找的结果。

代码实现

class Solution 
{
public:int searchInsert(vector<int>& nums, int target) {int left = 0, right = nums.size() - 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 right + 1;return right;}
};

结语:今日的刷题分享到这里就结束了,希望本篇文章的分享会对大家的学习带来些许帮助,如果大家有什么问题,欢迎大家在评论区留言~~~ 

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

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

相关文章

开源学习项目推荐

文章目录 koodo-reader凤凰架构学习项目NPS 内网穿透客户端 koodo-reader 项目地址&#xff1a;https://github.com/koodo-reader/koodo-reader 介绍&#xff1a;一个开源的阅读器&#xff0c;阅读pdf也有目录&#xff0c;作为epub阅读器和pdf阅读器看资料挺好 凤凰架构 项…

torch.gather(...)

1. Abstract 对于 pytorch 中的函数 torch.gather(input, # (Tensor) the source tensordim, # (int) the axis along which to indexindex, # (LongTensor) the indices of elements to gather*,sparse_gradFalse,outNone ) → Tensor有点绕&#xff0c;很多博客画各…

elastic:nested实现对满足条件的数组元素聚合查询

0. 引言 某些业务场景下&#xff0c;我们要对数组元素进行聚合查询&#xff0c;就需要用到nested数据类型&#xff0c;但部分场景是针对数组中指定的元素进行聚合&#xff0c;于是就需要对数组元素进行限定&#xff0c;今天来看看这种场景如何实现。 1. 数据准备 首先我们准…

【ECMAScript笔记一】初识JavaScript、变量的使用、数据类型包括哪些?

文章目录 1 初识JavaScript1.1 JS是什么1.2 JS的作用1.3 浏览器怎么执行JS1.4 编译性语言和解释型语言1.5 JS的组成1.6 JS的三种书写位置1.7 JS的注释1.8 JS的输入输出语句 2 变量2.1 变量的使用2.2 使用变量的注意点2.3 变量命名规范 3 数据类型3.1 简单数据类型3.1.1 数字型 …

6.s081操作系统Lab4: trap

文章目录 chapter 4概览4.1 CPU trap流程使用寄存器如果cpu想处理1个trap 4.2 用户态引发的trap4.2.1 uservec4.2.2 usertrap4.2.3 usertrapret和userretusertrapretuserret Lab4Backtrace (moderate)Alarm (hard) chapter 4 概览 trap的场景&#xff1a;系统调用&#xff0c…

2024年手把手教CleanMyMac X v4.14.6破解版安装激活图文教程

小编给您带来CleanMyMac X v4.14.6中文破解版&#xff0c;CleanMyMac X破解版是应用在MacOS上的一款Mac系统清理优化工具&#xff0c;使用cleanmymac x 中文破解版只需两个简单步骤就可以把系统里那些乱七八糟的无用文件统统清理掉&#xff0c;节省宝贵的磁盘空间。 CleanMyMac…

redis各种数据类型的应用场景

String应用场景 单值缓存 SET key value GET key 对象缓存 SET user:1 value(json格式数据)MSET user:1:name zhuge user:1:balance 1888 MGET user:1:name user:1:balance 分布式锁 SETNX product:10001 true //返回1代表获取锁成功 …

使用案例总结Vlookup函数的30种用法

1 基础用法 =VLOOKUP(A12,B$1:D$8,3,0) 2 批量查找 =VLOOKUP(A11:A13,A2:C8,3,0) 3 模糊查找 =VLOOKUP("*"&D2&"*",A:B,2,0) 4 模糊查找2 =VLOOKUP(D10&"??",A:B,2,0) 5 模糊查找3 =

pycharm通过ssh连接远程服务器的docker容器进行运行和调试代码

pycharm连接远程服务器的docker容器通常有两种方法&#xff1a; 第一种&#xff1a;pycharm通过ssh连接已在运行中的docker容器 第二种&#xff1a;pycharm连接docker镜像&#xff0c;pycharm运行代码再自动创建容器 第一种方法比较通用简单&#xff0c;作者比较推崇。 条件…

特氟龙材质PFA、FEP、PTFE三种氟塑料试剂瓶区别

PFA、FEP、PTFE三种材质&#xff0c;都具有良好的耐化学性和耐热性。适合用于微量分析&#xff0c;痕量分析&#xff0c;超痕量分析ICP-MS/OES/AAS分析等实验。PFA、FEP、PTFE是三种常见的氟塑料材料&#xff0c;它们在石油化工、机械、半导体电子等领域得到广泛应用。虽然它们…

展示一段比较简单的人工智能自动做模型的程序

人工智能是一种模拟或模仿人类智能的技术。它通过使计算机系统具有一定的认知能力和学习能力&#xff0c;使其能够自动完成一系列复杂的任务。人工智能可以在各个领域应用&#xff0c;包括图像识别、语音识别、自然语言处理、机器学习等。人工智能还可以用于解决各种问题&#…

Docker 的基本概念、优势、及在程序开发中的应用

Docker 是一种容器化平台,它通过使用容器化技术,将应用程序及其依赖性打包到一个独立的、可移植的容器中,从而实现应用程序的快速部署、可靠性和可扩展性。 下面是 Docker 的一些基本概念和优势: 容器:Docker 使用容器化技术,将应用程序及其依赖性打包到一个可移植的容器…

CUDA C:线程、线程块与线程格

相关阅读 CUDA Chttps://blog.csdn.net/weixin_45791458/category_12530616.html?spm1001.2014.3001.5482 第一百篇博客&#xff0c;写点不一样的。 当核函数在主机端被调用时&#xff0c;它会被转移到设备端执行&#xff0c;此时设备会根据核函数的调用格式产生对应的线程(…

docker在线安装minio

1、下载最新minio docker pull minio/minio 2、在宿主机创建 /usr/local/data/miniodocker/config 和 /usr/local/data/miniodocker/data,执行docker命令 docker run -p 9000:9000 -p 9090:9090 --name minio -d --restartalways -e MINIO_ACCESS_KEYminio -e MINIO_SECRET_K…

力扣225. 用队列实现栈【附进阶版】

文章目录 力扣225. 用队列实现栈示例思路及其实现两个队列模拟栈一个队列模拟栈 力扣225. 用队列实现栈 示例 思路及其实现 两个队列模拟栈 队列是先进先出的规则&#xff0c;把一个队列中的数据导入另一个队列中&#xff0c;数据的顺序并没有变&#xff0c;并没有变成先进后…

引领半导体划片机行业,实现钛酸锶基片切割的卓越效能

在当今快速发展的半导体行业中&#xff0c;博捷芯以其卓越的技术实力和精准的行业应用&#xff0c;脱颖而出&#xff0c;再次引领行业潮流。这次&#xff0c;他们将先进的BJX3356划片机技术应用于钛酸锶基片的切割&#xff0c;为半导体制造行业的进一步发展提供了强大的技术支持…

基于知识库的接口自动化测试——结果模型化方法与装置的分析

一、背景 随着自动化测试的设计理念不断完善、新的技术不断应用&#xff0c;自动化测试资产的积累代价和维护成本不断降低&#xff0c;自动化测试资产的数量持续增长。同时&#xff0c;随着DevOps的普及&#xff0c;应用研发过程越来越敏捷&#xff0c;自动化测试能力逐步从测…

js输入框部分内容不可编辑,其余正常输入,el-input和el-select输入框和多个下拉框联动后的内容不可修改

<tr>//格式// required自定义指令<e-td :required"!read" label><span>地区&#xff1a;</span></e-td><td>//v-if"!read && this.data.nationCode 148"显示逻辑<divclass"table-cell-flex"sty…

camera曝光时间

曝光和传感器读数 相机上的图像采集过程由两个不同的部分组成。第一部分是曝光。曝光完成后&#xff0c;第二步就是从传感器的寄存器中读取数据并传输&#xff08;readout&#xff09;。 曝光&#xff1a;曝光是图像传感器进行感光的一个过程&#xff0c;相机曝光时间&#xf…

技术阅读周刊第十期

技术阅读周刊&#xff0c;每周更新。 周四加了个班&#xff0c;周五没缓过来&#xff0c;就推迟到今天更新了 历史更新 20231117&#xff1a;第六期20231124&#xff1a;第七期20231201&#xff1a;第八期20231215&#xff1a;第九期 Golang: 14 Shorthand Tricks You Might No…