CC53.【C++ Cont】二分查找的普通模版

目录

1.知识回顾

2.关键点

特点

三个模版

普通的模版(有局限)

以LeetCode上的一道题为例:704. 二分查找

分析

引入二段性:分两段,舍一段,操作另一段(这个是二分查找的本质!)

代码

提交结果

当然也可以使用随机数来分两段

普通模版总结


1.知识回顾

之前在C语言专栏中的文章提到了二分查找,可复习:

E7.【C语言】练习:在一个有序数组中查找具体的某个数字n(二分查找)

本文将提炼出一些关键点

2.关键点

特点

算法细节较多,一 一介绍:

之前讲过二分查找的前提: 数组有序时才能使用二分查找,其实并不是这样!,

当数组满足某特定规律时,也可以使用二分查找(这个后面会介绍)

三个模版

有以下二分查找的固定格式,做题只需要照葫芦画瓢,注意先理解再记忆

普通的模版(有局限)

以LeetCode上的一道题为例:704. 二分查找

https://leetcode.cn/problems/binary-search/description/

给定一个 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]之间。
分析

暴力解法直接从左向右或从右向左找,这里不写,讲讲暴力解法的缺陷:每次只能比较一个数,时间复杂度为O(N)

注意到题目条件"一个 n 个元素有序的(升序)整型数组 nums ",那么可以利用数组的单调性对暴力解法优化

以nums = [-1,0,3,5,9,12], target = 9为例说明,现查找到3,发现target>3且数组单增,那么3的左侧是不需要查找的,继续查找3的右侧

引入二段性:分两段,舍一段,操作另一段(这个是二分查找的本质!)

对于上述单增数组有许多分段方式:

1.二分

即近似分成二等分

2.三分

将数组近似分成三等分

然后任意选一个节点来分段,例如:

3.四分

将数组近似分成四等分......

......

当然也可以使用随机数来分段

其中二分的时间复杂度是最低的,时间复杂度为O(logN),当然某些情况下使用随机数来分段时间复杂度也比较低

算法:设数组是单调递增的,对它平分两段:

比较nums[mid]和num[target]的大小,

1.nums[mid]==num[target],结束循环,返回结果

2.nums[mid]<num[target],依据二段性:分两段,舍一段,操作另一段

,舍弃[left,mid]段,去[mid,right]段寻找,那么更新left

left=mid+1;//right不变

nums[mid]>num[target],返回结果,依据二段性:分两段,舍一段,操作另一段

,舍弃[mid,right]段,去[left,mid]段,那么更新right

right=mid-1;//left不变

3.更新mid(有多种方法,上面提过了)

只需要循环上面三步,变化寻找的区间,最终一定可以找到结果

结束循环的两个条件:

1.nums[mid]==num[target],直接返回结果

2.left>right,(注:left==right,分的段是一个"点",只有一个元素,但也需要判断是否等于target,仍然需要循环),没有找到target

那么循环的条件是:left\leqslantright

代码
class Solution {
public:int search(vector<int>& nums, int target) {int left=0;int right=nums.size()-1;int mid;while(left<=right){mid=left+(right-left+1)/2;if (nums[mid]==target)return mid;if (nums[mid]>target)right=mid-1;if (nums[mid]<target)left=mid+1;  }return -1;//没找到target}
};

注:mid不要写成(left+right)/2!之前在L42.【LeetCode题解】四数之和(双指针思想) 从汇编角度分析报错原因文章提到过报错的原因,当数组过长时,加法可能导致溢出

防溢出的方法:(left+right)/2改为left+(right-left)/2或left+(right-left+1)/2

提交结果

同理三分法只需要将除数2改成3即可,四分法、五分法同理

mid=left+(right-left+1)/3;
当然也可以使用随机数来分两段
class Solution {
public:int search(vector<int>& nums, int target) {srand((unsigned int)time(nullptr));int left=0;int right=nums.size()-1;int mid;while(left<=right){mid=left+rand()%(right - left + 1);if (nums[mid]==target)return mid;if (nums[mid]>target)right=mid-1;if (nums[mid]<target)left=mid+1;   }return -1;}
};

注: 循环体中,如果最后更新mid将导致除0错误!

这样写是错误的:

class Solution {
public:int search(vector<int>& nums, int target) {srand((unsigned int)time(nullptr));int left=0;int right=nums.size()-1;int mid=left+rand()%(right - left + 1);while(left<=right){if (nums[mid]==target)return mid;if (nums[mid]>target)right=mid-1;if (nums[mid]<target)left=mid+1;mid=left+rand()%(right - left + 1);   }return -1;}
};

排查错误:

VS中进入调试模式

发生错误的地方是: mid = left + rand() % (right - left + 1),则mid=2+rand()%(1-2+1)=2+rand()%0,为除0错误,此时left仍然<=right,策略:先更新mid的值,这样进行if判断时能修改left和right的值,能及时退出循环,防止除0错误

提交结果:

普通模版总结

利用二段性填以下模版空缺的地方:

while(left<=right)
{int mid=left+(right-left+1)/2;if (......)return mid;if (......)right=mid-1;if (......)left=mid+1;  
}

注意1.判断条件 2.mid防溢出方法 3.left和right的更新方式

其他两个模版见下一篇文章

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

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

相关文章

lua脚本+Redission实现分布式锁

实现分布式锁最简单的一种方式&#xff1a;基于Redis 不论是本地锁还是分布式锁&#xff0c;核心都在于“互斥”。 在 Redis 中&#xff0c; SETNX 命令是可以帮助我们实现互斥。SETNX 即 set if not exists (对应 Java 中的 setIfAbsent 方法)&#xff0c;如果 key 不存在的…

设计模式之工厂模式(二):实际案例

设计模式之工厂模式(一) 在阅读Qt网络部分源码时候&#xff0c;发现在某处运用了工厂模式&#xff0c;而且编程技巧也用的好&#xff0c;于是就想分享出来&#xff0c;供大家参考&#xff0c;理解的不对的地方请多多指点。 以下是我整理出来的类图&#xff1a; 关键说明&#x…

MultiTTS 1.7.6 | 最强离线语音引擎,提供多音色无障碍朗读功能,附带语音包

MultiTTS是一款免费且支持离线使用的文本转语音&#xff08;TTS&#xff09;工具&#xff0c;旨在为用户提供丰富的语音包选项&#xff0c;实现多音色无障碍朗读功能。这款应用程序特别适合用于阅读软件中的离线听书体验&#xff0c;提供了多样化的语音选择&#xff0c;使得听书…

歌曲《忘尘谷》基于C语言的歌曲调性检测技术解析

引言 在音乐分析与数字信号处理领域&#xff0c;自动检测歌曲调性是一项基础且关键的任务。本文以C语言为核心&#xff0c;结合音频处理库&#xff08;libsndfile&#xff09;和快速傅里叶变换库&#xff08;FFTW&#xff09;&#xff0c;探讨如何实现调性检测&#xff0c;并通…

大某麦演唱会门票如何自动抢

引言 仅供学习研究&#xff0c;欢迎交流 抢票难&#xff0c;难于上青天&#xff01;无论是演唱会、话剧还是体育赛事&#xff0c;大麦网的票总是秒光。大麦网是国内知名的票务平台&#xff0c;热门演出票往往一票难求。手动抢票不仅耗时&#xff0c;还容易错过机会。作为一名…

1.3.3 tinyalsa详细介绍

一、TinyALSA 的背景与设计目标 1. 诞生背景 Android 音频需求的演变&#xff1a;早期 Android 系统使用标准 ALSA&#xff08;Advanced Linux Sound Architecture&#xff09;的用户空间库 alsa-lib&#xff0c;但因其复杂性&#xff08;代码庞大、依赖较多&#xff09;和资…

超越合并速度(merge speed):AI如何重塑开发者协作

李升伟 编译 AI 关于现代开发的讨论通常围绕着单一指标&#xff1a;合并速度&#xff08;merge speed&#xff09;。但在这一表面测量之下&#xff0c;隐藏着开发团队工作方式的一种更深刻的变革。让我们探讨开发者协作的微妙演变方式以及为什么传统生产力指标只讲述了一部分故…

如何找正常运行虚拟机

1.新建虚拟机。Linux centos7&#xff0c;给虚拟机改个名字不要放在c盘 2.安装操作系统。cd/dvd->2009.iso 启动虚拟机

深度学习:系统性学习策略(二)

深度学习的系统性学习策略 基于《认知觉醒》与《认知驱动》的核心方法论,结合深度学习的研究实践,从认知与技能双重维度总结以下系统性学习策略: 一、认知觉醒:构建深度学习的思维操作系统 三重脑区协同法则 遵循**本能脑(舒适区)-情绪脑(拉伸区)-理智脑(困难区)**的…

如何使用CSS解决一行有三个元素,前两个元素靠左排列,第三个元素靠右排列的问题

如图所示&#xff0c;我要把左边的场馆和区域信息靠左排列&#xff0c;价格信息靠右排列。如何使用CSS实现这种效果&#xff1f; 在这里&#xff0c;我使用了flexbox弹性布局&#xff0c;以下是我的实现代码 .name-info {display: flex;gap: 2px;justify-content: space-betwee…

USB传输模式

USB有四种传输模式: 控制传输, 中断传输, 同步传输, 批量传输 1. 中断传输 中断传输一般用于小批量, 非连续的传输. 对实时性要求较高. 常见的使用此传输模式的设备有: 鼠标, 键盘等. 要注意的是, 这里的 “中断” 和我们常见的中断概念有差异. Linux中的中断是设备主动发起的…

【Python 变量类型】

Python 是一种动态类型语言&#xff0c;变量类型在运行时自动确定&#xff0c;无需显式声明。以下是 Python 中核心变量类型的分类与用法详解&#xff1a; 一、基本数据类型 1. 数值类型 整数 (int) 支持正负数、零和二进制/八进制/十六进制表示&#xff1a; a 42 b 0o52 #…

Python基础:类的深拷贝与浅拷贝-->with语句的使用及三个库:matplotlib基本画图-->pandas之Series创建

一.类的深拷贝与浅拷贝 class CPU():pass class Disk():passclass Computer():#计算机由CPU和硬盘组成def __init__(self):self.cpu CPU()self.disk Disk()cpu CPU()#创建一个CPU对象 disk Disk()#创建一个硬盘对象#创建一个计算机对象 com Computer(cpu,disk) #变量&…

【SSM-SpringMVC(二)】Spring接入Web环境!本篇开始研究SpringMVC的使用!SpringMVC数据响应和获取请求数据

SpringMVC的数据响应方式 页面跳转 直接返回字符串通过ModelAndView对象返回 回写数据 直接返回字符串返回对象或集合 页面跳转&#xff1a; 返回字符串方式 直接返回字符串&#xff1a;此种方式会将返回的字符串与视图解析器的前后缀拼接后跳转 RequestMapping("/con&…

阅文集团C++面试题及参考答案

目录 能否不使用锁保证多线程安全? 面向对象的三个特性是什么?请分别解释。 构造函数和析构函数能否被继承? C++ 中函数重载是如何实现的? C 语言中是否支持函数重载? 什么是左值和右值?请举例说明。 C++ 中子类的构造和析构顺序是怎样的? C++ 中虚函数表的变化过…

【亲测有效】如何清空但不删除GitHub仓库中的所有文件(main分支)

如何清空但不删除GitHub仓库中的所有文件&#xff08;main分支&#xff09; 在项目开发过程中&#xff0c;有时我们需要清空GitHub仓库中的所有文件&#xff0c;同时保留仓库本身。这种情况常见于项目重构、代码重写或者需要重新开始一个项目时。本文将介绍一种有效的方法来清…

前端EXCEL插件,智表ZCELL产品V3.0 版本发布,底层采用canvas全部重构,功能大幅扩展,性能极致提升,满足千万级单元格加载

本次更新是底层全部重构&#xff0c;按照现代浏览器要求&#xff0c;采用canvas方式进行了重构&#xff0c;预留了将来扩展空间&#xff0c;特别是在大数据量性能提升方面有了较大提升&#xff0c;可以满足千万级单元格加载&#xff0c;欢迎大家体验使用。 体验地址&#xff1…

3DGS-to-PC:3DGS模型一键丝滑转 点云 or Mesh 【Ubuntu 20.04】【2025最新版!!】

一、引言 3D高斯泼溅(3DGS)是一种新兴的三维场景表示方法&#xff0c;可以生成高质量的场景重建结果。然而&#xff0c;要查看这些重建场景&#xff0c;需要特殊的高斯渲染器。大多数3D处理软件并不兼容3D高斯分布模型&#xff0c;但它们通常都兼容点云文件。 3DGS-to-PC项目提…

OpenHarmony 以太网卡热插拔事件接口无效

目录 1.背景 2.解决方案 1.背景 在OpenHarmony中调用以太网热插拔时间,发现热插拔没有任何回调,如下接口 import { ethernet } from @kit.NetworkKit;ethernet.on(interfaceStateChange, (data: object) => {console.log(on interfaceSharingStateChange: + JSON.…

C++ 跨平台开发挑战与深度解决方案:从架构设计到实战优化

C 凭借其高性能与底层控制能力&#xff0c;在游戏引擎、嵌入式系统、工业软件等领域占据核心地位。然而&#xff0c;跨平台开发过程中需应对硬件架构多样性、操作系统差异性、编译工具链碎片化等复杂问题。本文将从底层架构到上层应用&#xff0c;系统性剖析 C 跨平台开发的核心…