当前位置: 首页 > news >正文

【C++】二分查找算法习题

在这里插入图片描述
🎆个人主页:夜晚中的人海

在这里插入图片描述

今日语录:当你的才华不足以满足你的野心时,应该静下心来努力学习。

文章目录

  • ⭐一、二分查找
  • 🏝️二、在排序数组中查找元素的第一个和最后一个位置
  • 🎡三、搜索插入位置
  • 🚘四、x的平方根
  • 🚀五、寻找峰值
  • 🎆六、寻找排序数组中的最小值
  • 🎄七、0 ~ n - 1中缺失的数字

在使用二分查找算法前,我们首先要知道在什么情况下可以采用二分算法。我们普遍清楚在使用二分算法前 数据必须有序,这一回答是毋庸置疑的,但不完全正确,我们还需 判断题目中的数据是否有二段性,如果判断出有二段性,我们同样也可以采用二分算法,即使该数据不是有序的,下面就来一起看看二分查找的一些相关习题

⭐一、二分查找

题目链接:二分查找

题目描述:

在这里插入图片描述

解题思路:
1.这是一个最典型使用二分算法的题目,我们可以定义两个指针left和right分别指向数组的左右两区间

2.然后查找区间的中间点mid,看看中间点mid的值是否等于目标值

3.如果中间值大于目标值,说明从该区间开始一直到右区间的值都是大于目标值的,因此需要让right指针指向mid - 1的位置,让后重新执行步骤二的操作;相反如果小于目标值,说明从该区间开始一直到左区间的元素值都是小于目标值的,因此让left指向mid + 1的位置,再继续判断,直到找到目标值

代码实现:

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

🏝️二、在排序数组中查找元素的第一个和最后一个位置

题目链接:在排序数组中查找元素的第一个和最后一个位置

题目描述:

在这里插入图片描述

解题思路:
1.我们可以采用二分左边界和右边界的方法

2.在二分左边界时,我们可以根据中间点mid的落点来进行更新,如果中间值mid的值小于目标值,就让left指向mid + 1的位置,否则就让right指向mid的位置(注:不能指向mid - 1,有可能mid是最终结果

3.二分右边界时,同样也是根据mid的落点来进行判断,如果mid的值大于目标值,则让right指向mid - 1的位置,否则让left指向mid(注:同样不能指向mid + 1,mid可能是最终结果

代码实现:

class Solution {
public:vector<int> searchRange(vector<int>& nums, int target) {int n = nums.size();//标记左端点int begin = 0;if(n == 0)return {-1,-1};//二分左端点int left = 0,right = n - 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};elsebegin = left;//二分右端点left = begin,right = n - 1;while(left < right){int mid = left + (right - left + 1) / 2;if(nums[mid] <= target)left = mid;elseright = mid - 1;}return {begin,right};}
};

🎡三、搜索插入位置

题目链接:搜索插入位置

题目描述:

在这里插入图片描述

解题思路:
1.给两个指针left和right分别指向左边界和右边界,mid作为中间点,根据mid指向的元素进行分析

2.如果mid指向的元素小于等于目标值,则更新left,让left指向mid(mid可能是目标值),否则让right指向mid - 1的位置,不断循环此步骤

3.循环结束后,如果left指向的元素小于目标值,说明该数组没有目标值,则返回要插入的位置(即l:left + 1)否则返回left即可

代码实现:

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

🚘四、x的平方根

题目链接:x的平方根

题目描述:

在这里插入图片描述

解题思路:
1.暴力枚举,依次枚举[0,x]之间的所有数i,如果i * i大于x,则返回i - 1,否则返回i

2.二分算法,定义两个指针left和right,寻找中间点mid,如果mid * mid的值小于等于x,则找到结果,让left指向mid位置,返回left即可,否则让right指向mid - 1的位置

代码实现:

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;}else{right = mid - 1;}}return left;}
};

🚀五、寻找峰值

题目链接:寻找峰值

题目描述:

在这里插入图片描述

解题思路:
1.我们可以先来寻找数据是否有二段性,来看看能否使用二分算法

2.任取一个点i来进行判断,如果nums[i + 1] > nums[i],说明右侧区域一定存在山峰(注:右侧是负无穷),我们就可以去右侧寻找结果;相反nums[i] > nums[i + 1],说明左侧一定存在山峰,我们就可以去左侧寻找结果,判断出数据有二段性,我们就可以采用二分算法来解决

代码实现:

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

🎆六、寻找排序数组中的最小值

题目链接:寻找排序数组中的最小值

题目描述:
在这里插入图片描述

解题思路:
在这里插入图片描述
1.我们根据题目中的数组绘制如上的草图

2.根据草图我们发现[A,B]区间内的值是严格大于[C,D]区间内的值的,而且C的值是严格小于D的值的(注:C的值也可能等于D的值,当[C,D]区间内只有一个元素时),从而判断出数据有二段性,采用二分算法

3.初始化两个指针left,right,根据mid的落点来进行判断:如果mid落在[A,B]的区间内,说明mid位置的值是严格大于D点的值,则让left指向mid + 1的位置;如果mid落在[C,D]的位置上,说明mid的值是小于D点的值,因此让right指向mid

4.不断重复上述步骤,循环结束后left指向的元素就是我们要的结果,返回即可

代码实现:

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

🎄七、0 ~ n - 1中缺失的数字

题目链接:0 ~ n - 1中缺失的数字

题目描述:
在这里插入图片描述

解题思路:
1.先来判断数据是否有二段性,我们发现在缺失数据位置左边,数据的元素和数组的下标都是有序的;在缺失数据位置的右边,数据的元素和数组的下标都是无序的

2.我们就可以根据这一二段性来使用二分算法

代码实现:

class Solution {
public:int takeAttendance(vector<int>& records) {int n = records.size();int left = 0,right = n;while(left < right){int mid = left + (right - left) / 2;if(records[mid] == mid){left = mid + 1;}else{right = mid;}}return left;}
};
http://www.dtcms.com/a/519689.html

相关文章:

  • SharedPreferences的使用方法
  • PRCV 2025:文本何以成为 AGI 的必经之路?
  • 一位C++低延迟交易系统开发工程师的有趣开发经历
  • 如何为自己的店铺做网站建立的英语
  • 使用 Datasmith 将 Rhino 模型导入 Unreal Engine 5(UE5)
  • 怎么注册17做网站初学者做网站的软件
  • 【数据结构】基于Prim算法的最小生成树
  • Snipaste (截图贴图工具) 精准截图 中文免费版
  • C语言内存机制深度解析:指针运算、数组与字符串实战指南
  • 强化学习 深度学习 深度强化学习 有什么区别
  • 《FastAPI零基础入门与进阶实战》第23篇:mysql/HeidiSQL安装与利用HeidiSQL数据迁移
  • 可克达拉市建设局网站番禺厂家关键词优化
  • 注册公司在哪个网站系统微信crm系统如何添加
  • 深入 YOLOv5 数据增强:从 create_dataloader 到马赛克范围限定
  • 如果战国时候魏国,向西灭掉秦国为战略纵深,然后向东争夺天下 可行吗
  • Docker MailServer自建邮件服务器
  • 【CRC校验】CRC(循环冗余校验)算法介绍
  • SpringAI 内嵌模型 ONNX
  • 哪些平台制作网站硬件开发和软件开发
  • 网站设计功能编程网站有哪些
  • Volatility2在kali安装
  • Euler
  • 提示学习思想
  • 《图解技术体系》Wonderful talk AI ~~AI“Emerging”
  • k8s部署容器化应用-nginx2
  • 谈谈你对iOS的runtime和runloop的了解
  • Blender入门学习05 - 材质
  • 沂源网站网站页面设计图片素材
  • 做网站推广引流效果好吗黑料社2023
  • 抽水蓄能电站的最佳调度方案研究Matlab仿真