C++ 二分法

目录

1、704. 二分查找 

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

3、69. x的平方根

4、35. 搜索插入位置

5、852. 山脉数组的峰顶索引 

6、162. 寻找峰值

7、153. 寻找旋转排序数组中的最小值 

8、LCR 173. 点名 


1、704. 二分查找 

class Solution {
public:int search(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 if (nums[mid] > target)right = mid - 1;elsereturn mid;}return -1;}
};

思路:

首先,定义了两个变量leftright,分别表示数组的左边界和右边界。初始时,left被设置为数组的第一个元素的索引(0),right被设置为数组的最后一个元素的索引(nums.size() - 1)。

然后,使用一个循环来执行二分查找。循环条件是left小于等于right,这表示还存在未查找的区间。在二分查找算法中,使用left <= right作为循环条件是为了处理以下两种情况:

  1. 当查找区间只剩下一个元素时,即leftright指向同一个位置时,仍然需要进行一次比较。如果使用left < right作为循环条件,那么在这种情况下循环会提前结束,导致无法正确判断目标值是否存在。

  2. 当查找区间为空时,即left大于right时,循环条件为假,可以直接退出循环。这种情况下,表示目标值不存在于数组中。

在每次循环中,首先计算中间元素的索引mid,通过将左边界和右边界与左边界之差相加除以2得到。这样可以将查找区间缩小一半,并且不会超出整形范围。

接下来,通过比较中间元素nums[mid]和目标值target的大小关系,来确定下一步的查找方向。

  • 如果nums[mid]小于target,说明目标值在右半部分,将left更新为mid + 1,缩小查找区间为右半部分。
  • 如果nums[mid]大于target,说明目标值在左半部分,将right更新为mid - 1,缩小查找区间为左半部分。
  • 如果nums[mid]等于target,说明找到了目标值,直接返回mid作为结果。

如果循环结束时仍然没有找到目标值,即left大于right,则返回-1表示未找到。

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

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;int begin = 0;// 使用二分查找找到目标值的最左边界while (left < right) {int mid = left + (right - left) / 2;if (nums[mid] < target)left = mid + 1;elseright = mid;}// 检查最左边界的元素是否为目标值if (nums[left] != target)return {-1, -1};elsebegin = left;left = 0, 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};}
};

思路:寻找左右边界

首先,检查数组是否为空,如果为空,则直接返回{-1, -1}表示未找到目标值。

初始化左边界left为0,右边界right为数组长度减1。

使用二分查找来找到目标值的最左边界。循环条件是left < right

  1. 在每次循环中,计算中间元素的索引mid
  2. 比较中间元素nums[mid]与目标值target的大小关系:
    1. 如果nums[mid]小于目标值,说明目标值在右半部分,将left更新为mid + 1,缩小查找区间为右半部分。
    2. 如果nums[mid]大于等于目标值,说明目标值在左半部分,将right更新为mid,缩小查找区间为左半部分。
  3. 检查最左边界的元素是否为目标值。如果不是目标值,则表示未找到目标值,直接返回{-1, -1}。

将最左边界left赋值给begin,作为目标值的起始位置。

重新初始化leftright,继续使用二分查找来找到目标值的最右边界。循环条件是left < right

  1. 在每次循环中,计算中间元素的索引mid,。
  2. 比较中间元素nums[mid]与目标值target的大小关系:
    1. 如果nums[mid]小于等于目标值,将left更新为mid,缩小查找区间为右半部分。
    2. 如果nums[mid]大于目标值,将right更新为mid - 1,缩小查找区间为左半部分。
  3. 返回结果为{begin, right},其中begin为目标值的最左边界,right为目标值的最右边界。

3、69. x的平方根

​ 

思路:寻找左右边界 

首先,检查输入的数x是否小于1,如果是,则直接返回0。

然后,定义了两个变量leftright,分别表示查找区间的左边界和右边界。初始时,left被设置为1,right被设置为x

接下来,使用二分查找来逼近平方根的值。循环条件是left < right,这表示还存在未查找的区间。

在每次循环中,首先计算中间元素的值mid,通过将左边界和右边界相加除以2得到。这里使用了(right - left + 1) / 2来确保向上取整,以保证查找区间向上移动。

然后,通过比较中间元素的平方mid * mid与目标值x的大小关系,来确定下一步的查找方向。

  • 如果mid * mid小于等于x,说明平方根在右半部分,将left更新为mid,缩小查找区间为右半部分。
  • 如果mid * mid大于x,说明平方根在左半部分,将right更新为mid - 1,缩小查找区间为左半部分。

最后,循环结束时,leftright相等,表示找到了平方根的整数部分。返回left作为结果。

class Solution {
public:int mySqrt(int x) {if (x < 1)return 0;int left = 1, right = x;while (left < right) {long long mid = left + (right - left + 1) / 2;if (mid * mid <= x)left = mid;elseright = mid - 1;}return left;}
};

4、35. 搜索插入位置

思路:寻找左边界 

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;elseright = mid;}if (nums[left] < target)return right + 1;elsereturn 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 + 1) / 2;if (nums[mid] <= target)left = mid;elseright = mid - 1;}if (nums[left] < target)return right + 1;elsereturn right;}
};

5、852. 山脉数组的峰顶索引 

思路:寻找左边界  

class Solution {
public:int peakIndexInMountainArray(vector<int>& arr) {int left = 1, right = arr.size() - 2;while (left < right) {int mid = left + (right - left) / 2;if (arr[mid] < arr[mid + 1])left = mid + 1;elseright = mid;}return left;}
};

思路:寻找右边界  

class Solution {
public:int peakIndexInMountainArray(vector<int>& arr) {int left = 1, right = arr.size() - 2;while (left < right) {int mid = left + (right - left + 1) / 2;if (arr[mid] > arr[mid - 1])left = mid;elseright = mid - 1;}return left;}
};

两个解决方案都是有效的,并且都具有 O(log(n)) 的时间复杂度。它们的区别在于二分查找的条件判断。

  • 第一个解决方案中,二分查找的条件判断是 arr[mid] > arr[mid - 1],即判断当前位置的元素是否大于前一个元素。如果满足这个条件,则说明峰值在当前位置或右侧,将 left 更新为 mid;否则,峰值在左侧,将 right 更新为 mid - 1
  • 第二个解决方案中,二分查找的条件判断是 arr[mid] < arr[mid + 1],即判断当前位置的元素是否小于后一个元素。如果满足这个条件,则说明峰值在右侧,将 left 更新为 mid + 1;否则,峰值在左侧或当前位置,将 right 更新为 mid

6、162. 寻找峰值

 思路:寻找左边界 

class Solution {
public:int findPeakElement(vector<int>& nums) {int left = 0, right = nums.size() - 1;while (left < right) {int mid = left + (right - left) / 2;if (nums[mid] < nums[mid + 1])left = mid + 1;elseright = mid;}return left;}
};

 思路:寻找右边界  

class Solution {
public:int findPeakElement(vector<int>& nums) {int left = 0, right = nums.size() - 1;while (left < right) {int mid = left + (right - left + 1) / 2;if (nums[mid] > nums[mid - 1])left = mid;elseright = mid - 1;}return left;}
};

7、153. 寻找旋转排序数组中的最小值 

 思路:以最右端点为基准点进行比较,逐渐缩小范围。

class Solution {
public:int findMin(vector<int>& nums) {int left = 0, right = nums.size() - 1;int x = nums[right];while (left < right) {int mid = left + (right - left) / 2;if (nums[mid] > x)left = mid + 1;elseright = mid;}return nums[left];}
};

8、LCR 173. 点名 

思路:根据数组元素与下标相等和不相等划分两个区间,最后,如果元素与其下标不相等,则返回其下标即为所缺元素;如果元素与其下标相等,则所缺元素为数组最大元素加一,即为left或right加一。

class Solution {
public:int takeAttendance(vector<int>& records) {int left = 0, right = records.size() - 1;while (left < right) {int mid = left + (right - left) / 2;if (records[mid] == mid)left = mid + 1;elseright = mid;}return left == records[left] ? left + 1 : left;}
};

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

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

相关文章

lua函数定义

1.函数定义\n定义格式如下&#xff1a; optional_function_scope function function_name( argument1, argument2, argument3..., argumentn) function_body return result_params_comma_separated end optional_function_scope: 该参数是可选的指定函数是全局函数还是局部函数…

C++入门2

目录 前言&#xff1a; 引用 引用特性&#xff1a; 常引用&#xff1a; 使用场景&#xff1a; 1. 做参数 2. 做返回值 3.引用做返回值(方便读写返回变量&#xff09; 传值、传引用效率比较: 引用和指针的区别: 内联函数 auto关键字(C11) auto的使用细则&#xff1a…

访问raw.githubusercontent.com失败问题的处理

1 问题 GitHub上的项目的有些资源是放在raw.githubusercontent.com上的&#xff0c;通常我们在安装某些软件的时候会从该地址下载资源&#xff0c;直接访问的话经常容易失败。 # 安装operator kubectl apply -f https://raw.githubusercontent.com/oceanbase/ob-operator/2.1…

跟我学C++中级篇——单实例和静态化

一、单实例模式 在设计模式中&#xff0c;单实例模式几乎是所有语言中都非常常用的一种设计模式。它在实际的应用中也非常广泛&#xff0c;在很多的开源框架中&#xff0c;都可以看到单实例的影子。单实例&#xff0c;简单的就可以看做在整个应用周期中&#xff0c;只有一个对…

R3F(React Three Fiber)经验篇

之前一直在做ThreeJS方向&#xff0c;整理了两篇R3F&#xff08;React Three Fiber&#xff09;的文档&#xff0c;这是经验篇&#xff0c;如果您的业务场景需要使用R3F&#xff0c;可以参考一下这个文档。下面是目录&#xff0c;按照需求自取。 基础篇 ⬇️ R3F&#xff08;…

Android 内存优化内存泄漏处理

一:匿名内部类/非静态内部类 匿名内部类的泄漏原因&#xff1a;匿名内部类会隐式地持有外部类的引用.当外部类被销毁时&#xff0c;内部类并不会自动销毁&#xff0c;因为内部类并不是外部类的成员变量&#xff0c; 它们只是在外部类的作用域内创建的对象&#xff0c;所以内部…

力扣细节题:翻转二叉树

细节一&#xff1a;递归采用前序递归 细节二&#xff1a;采用交换节点而不是交换数据因为左右树交换的同时左右树的所有子节点都要交换 细节三&#xff1a;采用外置函数因为return如果在本函数内操作会存在必须返回空指针的问题 /*** Definition for a binary tree node.* s…

01_02_mysql09_MySQL的数据目录

MySQL的数据目录 学习再总结宋红康老师课程内容1.MySQL8的主要目录结构 安装好MySQL8之后&#xff0c;查看如下的目录结构 find / -name mysql1.1数据库文件的存放路径 MySQL数据库文件的存放路径&#xff1a;/var/lib/mysql/ 1.2相关命令目录 相关命令目录&#xff1a;/u…

opencascade15解析导出为step格式

#include "DisplayScene.h" // 包含显示场景的头文件 #include "Viewer.h" // 包含查看器的头文件// OpenCascade 包含 #include <BRepPrimAPI_MakeCylinder.hxx> // 创建圆柱体 #include <BinXCAFDrivers.hxx> // 二进制XCAF驱动程序 #includ…

番外篇 | YOLOv5+DeepSort实现行人目标跟踪检测

前言:Hello大家好,我是小哥谈。DeepSort是一种用于目标跟踪的深度学习算法。它结合了目标检测和目标跟踪的技术,能够在视频中准确地跟踪多个目标,并为每个目标分配一个唯一的ID。DeepSort的核心思想是将目标检测和目标跟踪两个任务进行联合训练,以提高跟踪的准确性和稳定性…

创建vue3项目(基础)

首先打开自己的目录文件输入指令cmd 出现命令行工具 输入指令vue create 项目名称 按回车 选择第三个自己配置 根据需求选择 回车 选择自己需要的版本 出现这个 一直按回车大约5下或者6下 创建完毕 结束 感谢观看

Spring 中的AOP 以及与 AspectJ AOP 的区别

AOP到底是什么&#xff0c;有什么作用&#xff1a; AOP&#xff08;Aspect-Oriented Programming&#xff0c;面向切面编程&#xff09;&#xff1a; 能够将那些与业务无关&#xff0c;却为业务模块所共同调用的逻辑或责任&#xff08;例如事务处理、日志管理、权限控制等&…

【EAI 024】RoboVQA: Multimodal Long-Horizon Reasoning for Robotics

Paper Card 论文标题&#xff1a;RoboVQA: Multimodal Long-Horizon Reasoning for Robotics 论文作者&#xff1a;Pierre Sermanet, Tianli Ding, Jeffrey Zhao, et.al. 作者单位&#xff1a;Stanford University, UC Berkeley, Meta 论文原文&#xff1a;https://arxiv.org/a…

【Linux】部署单机项目(自动化启动)---(图文并茂详细讲解)

目录 一 准备工作 1.1 连接服务器拷贝文件 1.2 解压 二 JDK安装 2.1 配置坏境变量 2.2 查看版本 三 Tomcat(自启动) 3.1 复制启动命令的位置 3.2 添加命令相关配置文件 3.2.1 配置jdk及tomcat目录 3.2.2 添加优先级 3.3 设置自启动命令 3.4 开放端口 四 My…

3_怎么看原理图之协议类接口之I2C笔记

I2C只连接I2CSCL与I2CSDA两根线&#xff0c;即2线制异步串行总线。 I2CSCL与I2CSDA两根线需要上拉电阻&#xff0c;目的是让电平有确定的状态。 发完8bit数据后&#xff0c;第9个电平拉低SDA为低电平。 比如传一个数据A0x410100 0001 IIC总线有多个从机设备的通信&#xff0c…

HTML + CSS 高频面试题

盒模型 CSS盒模型本质是一个盒子&#xff0c;封装周围的HTML元素&#xff0c;包括margin&#xff0c;border&#xff0c;padding&#xff0c;和content。 根据盒子大小的计算方式不同&#xff0c;盒模型分为两种&#xff1a; 1. 标准盒模型&#xff1a;box-sizing: content-b…

Spring Boot 笔记 025 主界面

1.1 路由搭建 1.1.1 安装vue router npm install vue-router4 1.1.2 在src/router/index.js中创建路由器&#xff0c;并导出 import { createRouter, createWebHistory } from vue-router//导入组件 import LoginVue from /views/Login.vue import LayoutVue from /views/La…

第9章 包和进程管理

9.1 软件安装 在 Linux 中安装软件分为以下三种方式&#xff1a; 源码安装 rpm包安装 yum/dnf安装 9.1.1 源码安装 软件准备 我们接下通过一个源码程序来演示如何安装这种软件。 [rootjock ~]# lltotal 60-rw-r--r--. 1 root root 59172 Feb 22 15:43 tree-2.0.4.tgz​#…

Aidex移动端项目入门

运行效果 项目源码下载 若依-ruoyi-AiDex-Uniapp: 若依-Ruoyi APP 移动解决方案&#xff0c;基于uniappuView封装的一套基础模版&#xff0c;开箱即用&#xff0c;免费开源&#xff0c;一份代码多终端适配&#xff0c;支持H5、支付宝小程序、微信小程序、APP&#xff0c;实现了…

改进Yolov5目标检测与单目测距 yolo速度测量-pyqt界面-yolo添加注意力机制

当设计一个结合了 YOLOv5 目标检测、单目测距与速度测量以及 PyQt 界面的毕业设计时&#xff0c;需要考虑以下几个方面的具体细节&#xff1a; 计算机视觉、图像处理、毕业辅导、作业帮助、代码获取&#xff0c;私聊会回复! YOLOv5 目标检测&#xff1a; 首先&#xff0c;选择…