【专题刷题】二分查找(一):深度解刨二分思想和二分模板

📝前言说明:

  • 本专栏主要记录本人的基础算法学习以及LeetCode刷题记录,按专题划分
  • 每题主要记录:(1)本人解法 + 本人屎山代码;(2)优质解法 + 优质代码;(3)精益求精,更好的解法和独特的思想(如果有的话)
  • 文章中的理解仅为个人理解。如有错误,感谢纠错

🎬个人简介:努力学习ing
📋本专栏:C++刷题专栏
📋其他专栏:C语言入门基础,python入门基础,C++学习笔记,Linux
🎀CSDN主页 愚润泽

视频

  • 二分查找算法介绍
  • 704. 二分查找
    • 朴素二分查找模板
  • 34. 在排序数组中查找元素的第一个和最后一个位置
    • 二分模板

二分查找算法介绍

因为我之前用python写题的时候也写过二分查找,也有点心得:
https://blog.csdn.net/tan_run/article/details/145514702
如今再学,任深感不足。通过 704 和 34 题再度感受和理解二分查找。


704. 二分查找

在这里插入图片描述

暴力解法:
遍历数组,依次和target比较,时间复杂度:O(n)

暴力解法的局限在于:每次只能判断一个数,没有利用数组升序的特点

更好的解法:二分查找。利用数组有序的特点,那怎么利用呢?

假设我们随机取一个下标i,将nums[i]target比较,如果nums[i] < target,又因为数组有序,所以:nums[i]左边的数都小于target,我们就可以直接排除左边的区间。

而上面所体现的也叫做二段性每次“选点”,通过该点可以让我们把探索区域划分成两份,并且能够排除一段区域。(只是选中点的时候,数学期望最小(易证),所以我们通常取中点,也叫做二分)

朴素二分查找模板

闭区间写法:
在这里插入图片描述

  • .......:根据二段性的特点来填写
  • while(left <= right):因为是闭区间写法,区间不为空,还要判断
  • left + (right - left) / 2:防溢出写法

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

在这里插入图片描述
暴力解法:
从头到尾遍历数组,时间复杂度:O(n)

二分查找(利用二段性):

  • 先找左端点:左端点左边的元素 < t;左端点及左端点右边的元素 >= t。于是,我们就可以发现二段性:当nums[mid] < t,左端点一定严格mid的右边[mid + 1, right](画图很好理解) ,left更新为mid + 1;当nums[mid] >= t的时候,左端点一定在[left, mid]mid位置不能排除,因为有可能mid就是左端点,right更新为mid
  • 上面这种方法其实是左闭右开区间的写法,right所在位置已经判断过了,循环条件while(left < right),因为当 left == right 的时候已经是空区间循环不变量right始终指向 >= t 的数字
  • 求中点操作:在左闭右开这种写法里面,当有两个中间值时(数组长度为偶数),必须要选择前一个:left + (right - left) / 2

重点:以上总结找左端点>=(左闭右开区间写法):

  • 如果nums[mid] < t,则右端点肯定在:[mid + 1, right]
  • 如果nums[mid] >= t,则右端点肯定在:[left, mid]
  • 循环条件,while(left < right)(因为是左闭右开的)
  • 求中点操作:left + (right - left) / 2 取前面的中点
  • 循环不变量:right始终指向第一个>= t的数

PS:多举例子,找极端例子看特殊情况

当然我们也可以直接写找右端点<=的:

  • 如果nums[mid] <= t,则右端点肯定在:[mid, right]
  • 如果nums[mid] > t,则右端点肯定在:[left, mid - 1]
  • 循环条件,while(left < right)(因为是左开右闭
  • 求中点操作:left + (right - left + 1) / 2 取后面的中点

其他方法:在>=的基础上转换:
在这里插入图片描述

题解代码:

class Solution {
public:vector<int> searchRange(vector<int>& nums, int target) {if(nums.size() == 0){return {-1, -1};}// 二分左端点 >= int left = 0, right = nums.size() - 1;while(left < right){int mid = left + (right - left) / 2; // 防止溢出if(nums[mid] < target)left = mid + 1;elseright = mid;}if(nums[right] != target)return {-1, -1}; // 代表没有targetint begin = right;// 找右端点(左端点不重置)left = begin, right = nums.size() - 1;while(left < right){int mid = left + (right - left + 1) / 2;if(nums[mid] <= target)left = mid;elseright = mid - 1;}return {begin, right};}
};

二分模板

在这里插入图片描述
口诀:

  • mid:下面出现 -1,上面就要 +1
  • if...else...:根据二段性写出

为什么呢?

首先,左右两种模板的取mid区别是:左边是向下取整,右边是向上取整

以右边模板为例:
右边模板的收缩范围:[mid, right][left, mid - 1]
如果此时剩余区间为:[right - 1, right],向下取整则mid = right - 1。如果,最后的判断进入if,则left = mid = right - 1和原来无异,就会死循环。
如果是向上取整:mid = right,进入ifleft = right,进入elseright = right - 1,两条语句都变化了,就不会死循环


🌈我的分享也就到此结束啦🌈
要是我的分享也能对你的学习起到帮助,那简直是太酷啦!
若有不足,还请大家多多指正,我们一起学习交流!
📢公主,王子:点赞👍→收藏⭐→关注🔍
感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!

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

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

相关文章

乡村治理数字化平台:信息技术赋能乡村振兴的深度探索

在信息化技术飞速发展的背景下&#xff0c;数字化转型已成为推动社会进步和治理现代化的关键力量。乡村治理数字化平台&#xff0c;作为信息技术在乡村治理领域的深度应用&#xff0c;正逐步成为提升乡村治理效能、推动乡村振兴的重要工具。本文将深入探讨乡村治理数字化平台的…

PyQt6基础_QTabWidget

目录 代码 运行 官方文档 PySide6.QtWidgets.QTabWidget - Qt for Python 代码 class TempWidget(QWidget):def __init__(self):super().__init__()self.tabs QTabWidget()self.tabs.tabBarClicked.connect(self.tabs_tabBarClicked)widget_tab1 QWidget()widget_tab2…

springboot在eclipse里面运行 run as 是Java Application还是 Maven

在 Eclipse 里运行 Spring Boot 项目时&#xff0c;既可以选择以“Java Application”方式运行&#xff0c;也可以通过 Maven 命令来运行&#xff0c;下面为你详细介绍这两种方式及适用场景。 以“Java Application”方式运行 操作步骤 在项目中找到带有 SpringBootApplicat…

怎样记忆Precision、Recall?

首先&#xff0c;明确符号&#xff1a; TP(True Posive)&#xff1a;标签为正&#xff0c;预测为正 TN(True Negative)&#xff1a;标签为负&#xff0c;预测为负 FP(False Positive)&#xff1a;标签为负&#xff0c;预测为正 FN(False Negative)&#xff1a;标签为正&#xf…

【C语言】C语言动态内存管理

前言 在C语言编程中&#xff0c;内存管理一直是程序员需要重点关注的领域。动态内存管理更是如此&#xff0c;它不仅涉及到内存的灵活分配和释放&#xff0c;还隐藏着许多潜在的陷阱。本文将从动态内存分配的基础讲起&#xff0c;逐步深入到常见的错误、经典笔试题分析&#x…

expres路由模块化

Express 路由模块化是实际开发中非常重要的一部分&#xff0c;可以让你的项目结构更清晰、维护更方便。 &#x1f9f1; 一、为什么要模块化&#xff1f; 随着项目变大&#xff0c;如果所有路由都写在 app.js 中&#xff0c;会很乱。使用模块化后可以&#xff1a; 功能解耦&a…

C语言——填充矩阵

C语言——填充矩阵 一、问题描述二、格式要求1.输入形式2.输出形式3.样例 三、实验代码 一、问题描述 编程实现自动填充nn矩阵元素数值&#xff0c;填充规则为&#xff1a;从第一行最后一列矩阵元素开始按逆时针方向螺旋式填充数值1&#xff0c;2&#xff0c;…&#xff0c;nn…

零基础上手Python数据分析 (22)案例实战]之利用 Matplotlib Seaborn 进行电商销售数据可视化分析

写在前面 —— 图表为刃,洞察先行!综合运用 Pandas、Matplotlib 与 Seaborn,点亮数据价值 本篇通过一个完整的案例实战,体验如何将数据分析与数据可视化紧密结合,让冰冷的数据转化为生动、直观、富有洞察力的视觉故事! 案例目标: 本篇博客将延续我们在第 17 篇案例中…

Java开发经验总结

只要删繁、捋清脉络&#xff0c;才能掌握本质&#xff01;只有创新才有价值&#xff0c;保持创新、保持学习&#xff01; 计划&#xff1a;UNIAPPSPRINGBOOT学习、SPRINGBOOTVUE新版学习、页面展示学习、PYTHON。 ***********************************************************…

深入解析:RocketMQ、RabbitMQ和Kafka的区别与使用场景

互联网大厂Java求职者面试&#xff1a;RocketMQ、RabbitMQ和Kafka的深入解析 故事场景&#xff1a;严肃且专业的面试官与架构师程序员马架构 在一家知名的互联网大厂&#xff0c;Java求职者正在接受一场严格的面试。面试官是一位经验丰富的技术专家&#xff0c;他将通过多轮提…

使用vue2开发一个医疗预约挂号平台-前端静态网站项目练习

对于后端开发的我&#xff0c;最近一直在学习前端开发&#xff0c;除了要学习一些前端的基础知识外&#xff0c;肯定少不了一些前端项目练习&#xff0c;就通过前端的编程知识 就简单做一个医疗预约挂号前端静态页面。这个网站主要是使用了vue2 的相关技术实现的。 主要实现了这…

MongoDB(docker版)备份还原

docker启动MongoDB docker run -d -p 27017:27017 --name my-mongo -v /mongodb/db:/data/db mongo备份MongoDB 使用mongodump备份数据库时&#xff0c;默认会将备份数据保存在当前工作目录下的dump文件夹中。 docker容器中默认备份在当前工作目录&#xff0c;所以此处指定当…

zkPass案例实战之合约篇

目录 一、contracts/contracts/ProofVerifier.sol 1. License 和 Solidity 版本 2. 导入依赖 3. 合约声明和默认分配器地址 4. 验证证明 5. 验证分配器签名 6. 验证验证者签名 7. 签名前缀处理 8. 签名恢复 总结 二、contracts/contracts/SampleAttestation.sol 1. …

ElasticSearch:高并发场景下如何保证读写一致性?

在Elasticsearch高并发场景下&#xff0c;可以通过以下多种方式来保证读写一致性&#xff1a; 等待主分片和副本分片都确认&#xff08;类似半同步机制&#xff09; 设置consistency参数&#xff1a;在写操作时&#xff0c;可以设置consistency参数来控制写操作的一致性级别。…

8、constexpr if、inline、类模版参数推导、lambda的this捕获、初始化列表、namespace---c++17

一、constexpr if&#xff1a;编译时条件分支 作用&#xff1a;在模板编程中&#xff0c;根据条件在编译时选择不同的代码路径&#xff0c;无需特化版本或复杂SFINAE技巧[替代SFINAE]。[SFINAE将在模版元编程再讲。下个月了。] 注意&#xff1a;默认使用了隐式inline 基本语法…

【Java设计模式及实践学习-第4章节-结构型模式】

第4章节-结构型模式 笔记记录 1. 适配器模式2. 代理模式3. 装饰器模式4. 桥接模式5. 组合模式6. 外观模式7. 享元模式8. 总结 1. 适配器模式 2. 代理模式 3. 装饰器模式 4. 桥接模式 5. 组合模式 6. 外观模式 7. 享元模式 Java语言中的String字符串就使用了享元模式&…

unity基础自学2.3:移动和抓握物品

文章目录 前言&#xff1a;1、基础配置①XR Interaction Toolkit②创建一个XR场景③示例文件实现④ 一键配置&#xff08;PICO Building Blocks&#xff09; 2、射线移动物品和抓握物品方法一&#xff1a;Grab Interactable方法二&#xff1a;prefab 3、Box Collider的作用与使…

pytest基础-new

规范 1、首先创建 py 文件命名以 test_ 开始或者以 _test 结尾 2、若是新建类&#xff0c;测试类需要以 Test_开头 3、测试用例&#xff08;方法&#xff09;需要以 test_开头 assert 断言 assert xx&#xff1a;判断 xx 为真 assert not xx&#xff1a;判断 xx 不为真 asse…

【华为OD机试真题】232、统计射击比赛成绩 | 机试真题+思路参考+代码分析(C++)

题目描述 给定一个射击比赛成绩单,包含多个选手若干次射击的成绩分数,请对每个选手按其最高3个分数之和进行降序排名,输出降序排 名后的选手ID序列 条件如下: 1.一个选手可以有多个射击成绩的分数,且次序不固定 2.如果一个选手成绩少于3个,则认为选手的所有成绩无效,排名…

⭐Unity 开发 | 如何通过 NTP 网络时间实现精准的跨平台时间同步【附完整源码 + UI 模块 + 偏差分析】

&#x1f3ae; 项目实战 | 实现一套精确、可视化的游戏时间同步机制&#xff0c;让你的多人在线游戏摆脱“时间不一致”噩梦&#xff01; 效果如图&#xff1a; &#x1f4cc; 一、前言&#xff1a;为什么不能只信本地时间&#xff1f; 在 Unity 游戏开发中&#xff0c;时间几…