【算法】二分查找

news/2024/11/15 8:22:19/



快乐的流畅:个人主页


个人专栏:《算法神殿》《数据结构世界》《进击的C++》

远方有一堆篝火,在为久候之人燃烧!

文章目录

  • 引言
  • 一、二分查找
  • 二、查找元素的第一个和最后一个位置
  • 三、x的平方根
  • 四、搜索插入位置
  • 五、山脉数组的峰顶索引
  • 六、寻找峰值
  • 七、寻找旋转数组中的最小值
  • 八、寻找旋转数组中的最小值 ||
  • 总结

引言

二分查找,实际上也是左右双指针的变形,本质是利用数组的二段性进行查找。总共有三个模板:朴素二分、左边界二分、右边界二分

一、二分查找


思路:

  1. 这道题就是标准的朴素二分,也是最简单最基础的二分
  2. 循环条件:left <= right
  3. 求中点(两种方法都可以):
    • int mid = left + (right-left)/2;//求左中点
    • int mid = left + (right-left+1)/2;//求右中点
  4. 上述求中点方法,可以防止溢出
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;else return mid;}return -1;}
};

二、查找元素的第一个和最后一个位置


思路:

  1. 本题便用到了左边界二分和右边界二分
  2. 循环条件:left < right(注意:判断等于会死循环)
  3. 左边界二分:int mid = left + (right-left)/2;//求左中点
  4. 右边界二分:int mid = left + (right-left+1)/2;//求右中点
  5. 出循环后,还要再判断当前位置的值是否为target
class Solution
{
public:vector<int> searchRange(vector<int>& nums, int target){if(nums.size() == 0) return {-1, -1};int begin = -1, end = -1;int left = 0, right = nums.size() - 1;while(left < right){int mid = left + (right-left)/2;if(nums[mid] >= target) right = mid;else left = mid + 1;}if(nums[left] == target) begin = left;left = 0, right = nums.size() - 1;while(left < right){int mid = left + (right-left+1)/2;if(nums[mid] <= target) left = mid;else right = mid - 1;}if(nums[left] == target) end = left;return {begin, end};}
};

三、x的平方根


思路:

  1. 右边界二分
  2. 注意mid*mid数值太大,int 会溢出,所以改成long long
class Solution
{
public:int mySqrt(int x){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 right;}
};

四、搜索插入位置


思路:

  • 左边界二分
class Solution
{
public:int searchInsert(vector<int>& nums, int target){if(target > nums.back()) return nums.size();int left = 0, right = nums.size() - 1;while(left < right){int mid = left + (right-left)/2;if(nums[mid] >= target) right = mid;else left = mid + 1;}return left;}
};

五、山脉数组的峰顶索引


思路:

  • 左边界二分(右边界也可以)
class Solution
{
public:int peakIndexInMountainArray(vector<int>& arr){int left = 0, right = arr.size() - 1;while(left < right){int mid = left + (right-left)/2;if(arr[mid] >= arr[mid+1]) right = mid;else left = mid + 1;}return right;}
};

六、寻找峰值


思路:

  • 左边界二分(右边界也可以)
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]) right = mid;else left = mid + 1;}return left;}
};

七、寻找旋转数组中的最小值


思路:

  1. 每次选取right指向的值,作为比较的基准值
  2. 左边界二分
class Solution
{
public:int findMin(vector<int>& nums){int left = 0, right = nums.size() - 1;while(left < right){int mid = left + (right-left)/2;if(nums[mid] <= nums[right]) right = mid;else left = mid + 1;}return nums[left];}
};

八、寻找旋转数组中的最小值 ||


思路:

  1. 这题是上题的变形,主要改变是存在重复元素
  2. 还是左边界二分,不过在 nums[mid] == nums[right] 时,- -right 即可
class Solution
{
public:int findMin(vector<int>& nums){int left = 0, right = nums.size() - 1;while(left < right){int mid = left + (right-left)/2;if(nums[mid] < nums[right]) right = mid;else if(nums[mid] == nums[right]) --right;else left = mid + 1;}return nums[left];}
};

总结

二分查找,是一种十分高效的查找算法,时间复杂度为O(logN),在数组具有二段性时便可应用。

同时,只要掌握并理解了二分的模板,它便是最简单、最容易的一类题型~


真诚点赞,手有余香


http://www.ppmy.cn/news/1426569.html

相关文章

吴恩达机器学习笔记 三十五 异常检测与监督学习

什么时候选择异常检测&#xff1f; 正样本 ( y 1 ) 的数量非常少 负样本 ( y 0 ) 的数量非常多 有很多不同的异常&#xff0c;现有的算法不能从正样本中得知什么是异常&#xff0c;或未来可能出现完全没见过的异常情况。 例如金融欺诈&#xff0c;隔几个月或几年就有新的…

格瑞纳电子邀您参观2024杭州快递物流展

参展企业介绍 北京格瑞纳电子产品有限公司是一家立足于专业科学技术领域集产品代理、培训咨询和个性化增值服务的高科技公司&#xff0c;于2009年成立于北京&#xff0c;立足于复杂系统仿真领域&#xff0c;主营业务以仿真分析软件产品为中心&#xff0c;提供集产品研发、销售…

Android Jetpack学习系列——Room

关于Room&#xff1a; Room是Android Jetpack组件之一&#xff0c;旨在为Android应用程序提供一种简单、强大且易于使用的本地数据库访问解决方案。 关键特性&#xff1a; 1.基于SQLite封装&#xff1a;Room是基于SQLite数据库引擎构建的&#xff0c;提供了面向对象的API来与…

bug是测不完的,根本测不完

恼火&#xff0c;测不完的bug&#xff0c;异常场景的bug要测&#xff0c;样式的问题要测&#xff0c;一旦变动一个需求&#xff0c;还要全盘通策&#xff0c;活生生的卖命啊&#xff01; 简直不知道要怎么测试了。 那就只走正常的业务流程&#xff0c;时间多再异常场景测试吧。…

包装类的认识

前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; hellohello~&#xff0c;大家好&#x1f495;&#x1f495;&#xff0c;这里是E绵绵呀✋✋ &#xff0c;如果觉得这篇文章还不错的话还请点赞❤️❤️收藏&#x1f49e; &#x1f49e; 关注&#x1f4a5;&#x1…

PostgreSQL 窗口函数汇总

文章目录 前言一、什么是窗口函数?二、常用的4类窗口函数三、PARTITION BY 子句四、窗口函数示例1. 聚合计算1.1 sum() 函数1.2 count() 函数1.3 avg() 函数2. 分组排序2.1 row_number() 函数2.2 rank() 函数2.3 dense_rank() 函数3. 分组查询

机器学习波士顿房价

流程 数据获取导入需要的包引入文件,查看内容划分训练集和测试集调用模型查看准确率 数据获取 链接&#xff1a;https://pan.baidu.com/s/1deECYRPQFx8h28BvoZcbWw?pwdft5a 提取码&#xff1a;ft5a --来自百度网盘超级会员V1的分享导入需要的包 import pandas as pd imp…

安全开发实战(1)--Cdn

目录 安全开发专栏 CDN介绍 1.信息收集阶段 1.1判断CDN是否存在 1.1.1, One 1.1.2,Two(改进) 1.1.3,进行整合 增加输入功能 1.1.4 批量读取监测存储(进行测试) 问题1: 问题2: 解决方案: 1.1.4 基本编写完成 命令框中: cdn存在.txt 总结 这里我是根据整个渗透测…