【刷题(13)】二分查找

一、二分查找基础

(1)int mid = ((right - left) >> 1) + left;
(2)lower_bound的底层实现

int lower_bound(vector<int>& nums, int x) 
{int left = 0;int right = nums.size() - 1;// 区间为 左闭右闭while (left <= right) {int mid = left +(right - left) / 2;if (x > nums[mid]) {left = mid + 1;}else {right = mid - 1;	}}return left;
}

upper_bound用法和上面类似。只是把lower_bound的 【大于等于】 换成 【大于】 。仿函数等等全是相同的用法
底层实现

int upper_bound(vector<int>& nums, int x) {int left = 0;int right = nums.size() - 1;while (left <= right) {int mid = left +(right - left) / 2;if (x >= nums[mid]) {       //这里是大于等于left = mid + 1;}else {right = mid - 1;	}}return left;
}

(3)binary_search()实现

template <class ForwardIterator, class T>
bool binary_search (ForwardIterator first, ForwardIterator last, const T& val)
{first = std::lower_bound(first,last,val);return (first!=last && !(val<*first));
}

(5)二分查找

int search(vector<int>& nums, int target){// 二分查找区间[left, right),初始为整个区间int left = 0;   int right = nums.size();// 找到首个大于target的值while(left < right){int mid = left + ((right - left) >> 1);if(nums[mid] > target){right = mid;    // 找到一个大于target的值,暂存并在左半区间继续查找}else{left = mid + 1; // 没有找到大于target的值,在右半区间继续查找}}return right;}

二、35. 搜索插入位置

1 题目

在这里插入图片描述

2 解题思路

(1)由于是排序数组,所以可以使用二分法来进行目标值查找
(2)假设题意是叫你在排序数组中寻找是否存在一个目标值,那么训练有素的读者肯定立马就能想到利用二分法在 O(log⁡n)的时间内找到是否存在目标值。但这题还多了个额外的条件,即如果不存在数组中的时候需要返回按顺序插入的位置,那我们还能用二分法么?答案是可以的,我们只需要稍作修改即可。

考虑这个插入的位置 pos,它成立的条件为:

nums[pos−1]<target≤nums[pos]
其中 nums 代表排序数组。由于如果存在这个目标值,我们返回的索引也是 pos,因此我们可以将两个条件合并得出最后的目标:「在一个有序数组中找第一个大于等于 target的下标」。

问题转化到这里,直接套用二分法即可,即不断用二分法逼近查找第一个大于等于 target的下标 。下文给出的代码是笔者习惯的二分写法,ans 初值设置为数组长度可以省略边界条件的判断,因为存在一种情况是 target 大于数组中的所有数,此时需要插入到数组长度的位置。

3 code

class Solution {
public:int searchInsert(vector<int>& nums, int target) {int n=nums.size();int left=0;int right=n-1;int ans=n;while(left<=right){// >>1相当于/2int mid= left+((right-left)>>1);//移动逻辑if(target<=nums[mid]){ans=mid;right=mid-1;}else{left=mid+1;}}return ans;}
};

三、74. 搜索二维矩阵

1 题目

在这里插入图片描述

2 解题思路

(1)由于每行的第一个元素大于前一行的最后一个元素,且每行元素是升序的,所以每行的第一个元素大于前一行的第一个元素,因此矩阵第一列的元素是升序的。
(2)我们可以对矩阵的第一列的元素二分查找,找到最后一个不大于目标值的元素,然后在该元素所在行中二分查找目标值是否存在。

3 code

class Solution {
public:bool searchMatrix(vector<vector<int>>& matrix, int target) {// 我们可以对矩阵的第一列的元素二分查找,找到最后一个不大于目标值的元素auto row=upper_bound(matrix.begin(),matrix.end(),target,[](const int b, const vector<int>&a){return b<a[0];});if(row==matrix.begin()){return false;}--row;//然后在该元素所在行中二分查找目标值是否存在。return binary_search(row->begin(),row->end(),target);}
};

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

1 题目

在这里插入图片描述

2 解题思路

在这里插入图片描述

3 code

class Solution {
private:/*** @brief 返回首个大于target的元素索引,如果不存在,返回数组长度n* @param nums: 输入数组* @param target: 目标值* @return: 目标值索引*/int search(vector<int>& nums, int target){// 二分查找区间[left, right),初始为整个区间int left = 0;   int right = nums.size();// 找到首个大于target的值while(left < right){int mid = left + ((right - left) >> 1);if(nums[mid] > target){right = mid;    // 找到一个大于target的值,暂存并在左半区间继续查找}else{left = mid + 1; // 没有找到大于target的值,在右半区间继续查找}}return right;}
public:vector<int> searchRange(vector<int>& nums, int target) {// 首个target如果存在,一定是首个大于target-1的元素int start = search(nums, target - 1);if(start == nums.size() || nums[start] != target){return {-1, -1};    // 首个target不存在,即数组中不包含target}// 找到首个大于target的元素,最后一个target一定是其前一位int end = search(nums, target);return {start, end - 1};}
};

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

1 题目

在这里插入图片描述

2 解题思路

这道题要在一个旋转了的有序数组中搜索目标值,要求时间复杂度为 O(logn)。这个时间复杂度只能首先尝试二分查找,但是二分查找的前提是数组有序,这个数组并不满足,还可以用吗?

先别急,虽然这个数组不是整体有序,但它是局部有序的,我们尝试二分着去做看看会发生什么。

二分每次都需要取中点 mid,对于这个旋转的有序数组:

  • 如果当前区间 [left, right) 分别在两端有序区间之内,那么就按二分查找去做即可。
  • 如果当前区间 [left, right) 是跨越了两端有序子区间的,那么中间点 mid 总会把当前区间 [left, right] 分成两段,一段是有序的,一段是无序的:

(1)如果 nums[mid] > nums[left],肯定是左半区间有序;

(2)如果 nums[mid] < nums[right-1],肯定是右半区间有序;【之所以 -1,是因为 right 初始为数组长度 n,直接取 right 会导致越界】
在这里插入图片描述
二分的策略还是一样的,二分的关键是要判断 target 落在哪个区间。我们只能取有序的那个区间来比较,因为只有区间有序,才能 通过端点值的大小比较判断是否落入对应的区间

在这里插入图片描述
因此我们只要能够每次判断目标值落到哪个区间,就可以通过二分排除另一半的区间,并不一定要求必须整个数组有序。
在这里插入图片描述

3 code

class Solution {
public:int search(vector<int>& nums, int target) {int left = 0;              // 二分查找左边界(左闭)int right = nums.size();    // 二分查找右边界(右开)while(left < right){int mid = left + ((right - left) >> 1);   if(nums[mid] == target){// 找到目标值,直接返回索引return mid;}if(nums[left] < nums[mid]){// 左半区间有序if(nums[left] <= target && target < nums[mid]){right = mid;    // 目标值落入左半区间,更新右边界}else{  left = mid + 1; // 否则在右半区间查找}}else{// 右半区间有序if(nums[mid] < target && target <= nums[right -1]){left = mid + 1; // 目标值落入右半区间,更新左边界}else{right = mid;    // 否则在左半区间查找}}}return -1;  // 如果退出循环,说明没有找到目标值,返回-1}
};

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

1 题目

在这里插入图片描述

2 解题思路

3 code

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

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

相关文章

基于python实现生命游戏

文章目录 一、生命游戏是什么二、生命游戏规则解释1.相邻细胞2.细胞状态 三、代码实现1.邻居细胞2.更新状态 四、整体代码 一、生命游戏是什么 生命游戏&#xff08;Game of Life&#xff09;是由英国数学家约翰何顿康威在1970年发明的一种细胞自动机&#xff08;Cellular Aut…

(超详细)字符函数和字符串函数【上】

前言 C 语言中对字符和字符串的处理很是频繁&#xff0c;但是 C 语言本身是没有字符串类型的&#xff0c;字符串通常放在 常量字符串 中或者 字符数组 中。 字符串常量 适用于那些对它不做修改的字符串函数 . 1.求字符串长度函数 strlen函数 我们要求一个字符串函数的长度…

Firefox国际版

Firefox国际版官方网址&#xff1a; Download the Firefox Browser in English (US) and more than 90 other languagesEveryone deserves access to the internet — your language should never be a barrier. That’s why — with the help of dedicated volunteers around…

C语言序列化和反序列化--TPL(一)

TPL TPL说明网站 C语言中高效的序列化 您可以使用tpl快速轻松地存储和重新加载C数据。Tpl是一个用于序列化C数据的库。数据以自然二进制形式存储。该API很小&#xff0c;并试图保持“不碍事”。Tpl可以序列化许多C数据类型&#xff0c;包括结构。Tpl与文件、内存缓冲区和文件…

【数据结构:排序算法】堆排序(图文详解)

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;数据结构课程学习 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 &#x1f369;1.大堆和小堆 &#x1f369;2.向上调整算法建堆和向下调整算法建堆&#xff1a;…

Kafka原生API使用Java代码-生产者-分区策略-默认分区策略轮询分区策略

文章目录 1、代码演示1.1、pom.xml1.2、KafkaProducerPartitioningStrategy.java1.2.1、ProducerConfig.LINGER_MS_CONFIG取 0 值得情况&#xff0c;不轮询1.2.2、ProducerConfig.LINGER_MS_CONFIG取 0 值得情况&#xff0c;轮询1.2.3、ProducerConfig.LINGER_MS_CONFIG取 1000…

B/S架构+java语言+Mysqladr数 据 库ADR药物不良反应监测系统源码 ADR药物不良反应监测系统有哪些作用?

B/S架构&#xff0b;java语言&#xff0b;Mysqladr数 据 库ADR药物不良反应监测系统源码 ADR药物不良反应监测系统有哪些作用&#xff1f; 药物不良反应(ADR)是指在合格药物以正常用量和用法用于预防、诊断、治疗疾病或调节生理功能时所发生的意外的、与防治目的无关的、不利或…

AI Agent智能体概述及原理

AI Agent概述 AI Agent旨在理解、分析和响应人类输入&#xff0c;像人类一样执行任务、做出决策并与环境互动。它们可以是遵循预定义规则的简单系统&#xff0c;也可以是根据经验学习和适应的复杂、自主的实体&#xff1b;可以是基于软件的实体&#xff0c;也可以是物理实体。…

大模型“1元购”?AI公司加速奔向应用端“大航海时代”

自字节跳动发布豆包大模型&#xff0c;互联网大厂纷纷就位&#xff0c;击穿“地板价”的打法从C端向B端拓展。这也成为今年“618”最亮眼的价格战。 5月15日&#xff0c;字节跳动率先宣布豆包大模型已通过火山引擎开放给企业客户&#xff0c;大模型定价降至0.0008元/千Tokens&…

设计模式20——职责链模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用&#xff0c;主要是下面的UML图可以起到大作用&#xff0c;在你学习过一遍以后可能会遗忘&#xff0c;忘记了不要紧&#xff0c;只要看一眼UML图就能想起来了。同时也请大家多多指教。 职责链模式&#xff08;Chain …

FreeRTOS【8】二值信号量使用

1.开发背景 FreeRTOS 提供了队列可以在线程间快速交换信息&#xff0c;那么还有没有其他交互渠道&#xff1f;答案是有的&#xff0c;相对于队列传递信息&#xff0c;还有更轻量级的线程唤醒操作&#xff0c;那就是信号量&#xff0c;而二值信号量就是最简单的一种。 二值信号量…

C++模拟实现stack和queue

1 stack 1.1概念 stl栈 1.2栈概念 1.3代码 2 queue 2.1概念 stl队列 2.2队列概念 2.3代码

网上打印资料A4纸一般多少钱一张

我们知道&#xff0c;在打印需求上A4纸&#xff08;210mmx297mm&#xff09;是较为常见的打印用纸&#xff0c;同时因为纸张的不同在价格上也存在一定的差异。当然&#xff0c;因在网上打印平台打印资料&#xff0c;能够降低一定的租金个人工成本。 因此&#xff0c;在网上打印…

Swift 中的Getter 和 Setter

目录 前言 1. 什么是Getter和Setter 1.定义 2.作用 2.属性 1.存储属性 2.计算属性 3.属性观察者 3. 使用 Getter 和 Setter 的场景 1.数据转换 2.懒加载 3.数据验证和限制 4.触发相关操作 4.自定义Getter 和 Setter 5. 参考资料 前言 属性是 Swift 编程中的基本…

关于 Spring 是什么

Spring 是什么 我们通常所说的 Spring 指的是 Spring Framework&#xff08;Spring 框架&#xff09;&#xff0c;它是⼀个开源框架&#xff0c;有着活跃⽽庞⼤的社区&#xff0c;这就是它之所以能⻓久不衰的原因。Spring ⽀持⼴泛的应⽤场景&#xff0c;它可以让 Java 企业级的…

九章云极DataCanvas公司DingoDB完成中国信通院权威多模数据库测试

2024年5月16日&#xff0c;九章云极DataCanvas公司自主研发和设计的开源多模向量数据库DingoDB顺利完成中国信息通信研究院&#xff08;以下简称中国信通院&#xff09;多模数据库产品测试。本次测试的成功标志着DingoDB在技术能力、性能表现和产品稳定性方面得到了权威机构的高…

python深入探索斐波那契数列:代码示例与不满足的外围条件

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、斐波那契数列的初步实现 二、外围条件的不满足情况 总结 一、斐波那契数列的初步实现 …

存储型XSS

前言 什么是存储型xss&#xff1a; 提交恶意xss数据&#xff0c;存入数据库中&#xff0c;访问时触发。 存储型xss和反射型xss区别&#xff1a; 存储型存入数据库中&#xff0c;可持续时间长&#xff0c;而反射型持续时间短&#xff0c;仅对本次访问有影响&#xff0c;反射型一…

中华活页文选高中版投稿发表

《中华活页文选&#xff08;高中版&#xff09;》创刊于1960年&#xff0c;是中宣部所属中国出版传媒股份有限公司主管、中华书局主办的国家级基础教育期刊&#xff0c;曾获得“中国期刊方阵双效期刊”、国家新闻出版广电总局推荐的“百种优秀报刊”等荣誉称号。本刊以高中学科…

Day 6:2981. 找出出现至少三次的最长特殊子字符串 I

Leetcode 2981. 找出出现至少三次的最长特殊子字符串 I 给你一个仅由小写英文字母组成的字符串 s 。 如果一个字符串仅由单一字符组成&#xff0c;那么它被称为 特殊 字符串。例如&#xff0c;字符串 “abc” 不是特殊字符串&#xff0c;而字符串 “ddd”、“zz” 和 “f” 是特…