【算法】二分查找

embedded/2024/10/21 11:50:53/



快乐的流畅:个人主页


个人专栏:《算法神殿》《数据结构世界》《进击的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/embedded/6420.html

相关文章

TensorFlow 的基本概念和使用场景

TensorFlow是一个开源机器学习框架&#xff0c;由Google开发。它通过使用数据流图来表示计算任务&#xff0c;并使用张量&#xff08;Tensor&#xff09;来表示数据&#xff0c;从而实现了高效的计算。 TensorFlow的基本概念包括以下几点&#xff1a; 1. 张量&#xff08;Ten…

Python模块之logging

官方文档 常见用法 logging模块是Python标准库中用于记录日志的模块。它提供了灵活且可配置的日志记录功能&#xff0c;可以用于在应用程序中捕获和输出各种级别的日志消息。以下是logging模块的常见用法示例&#xff1a; python import logging# 配置日志记录器 logging.b…

设计模式学习笔记 - 开源实战一(上):通过剖析JDK源码学习灵活应用设计模式

工厂模式在 Calendar 类中的应用 在前面讲到工厂模式的时候&#xff0c;大部分工厂类都是以 Factory 作为后缀来命名&#xff0c;并且工厂类主要负责创建对象这样一件事情。但在实际的项目开发中&#xff0c;工厂类的设计更加灵活。我们来看下&#xff0c;工厂模式在 Java JDK…

继东风一汽通信后,天磊咨询再次与东风集团达成深度业务合作

&#xff08;天磊咨询总经理&#xff1a;刘文喜&#xff09; 在风起云涌的市场激战中&#xff0c;天磊咨询凭借其出类拔萃的专业实力与服务品质&#xff0c;犹如一颗璀璨明星般脱颖而出&#xff0c;成功与赫赫有名的东风集团达成业务合作。这一合作的达成&#xff0c;不单彰显…

React + 项目(从基础到实战) -- 第八期

ajax 请求的搭建 引入mockAP接口设计AJAX 通讯 前置知识 HTTP 协议 , 前后端通讯的桥梁API : XMLHttpRequest 和 fetch常用工具axios mock 引入 Mock.js (mockjs.com) 使用 mockJS 前端代码中引入 mockJs定义要模拟的路由 , 返回结果mockJs 劫持ajax请求(返回模拟的结果)…

linux设备树-of_parse_phandle_with_args

1.设备树实例 interrupt-controller1 { compatible "vendor,gic"; #interrupt-cells <2>; interrupt-controller; reg <0x01 0x1000>; }; deviceA { compatible "vendor,device-a"; reg <0x02 0x100>; interrupts <&interr…

Spark---RDD的创建分类和基础操作算子详解

一、RDD的创建 原生api提供了两种创建方式&#xff0c;一种就是读取文件textFile&#xff0c;还有一种就是加载一个scala集合parallelize。当然&#xff0c;也可以通过transformation算子来创建的RDD。 //创建RDD//加载数据&#xff0c;textFile&#xff08;参数1&#xff0c;…

聚观早报 | 理想L6正式发布;Meta发布Llama 3

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 4月20日消息 理想L6正式发布 Meta发布Llama 3 比亚迪秦L内饰曝光 小米14 Ultra推送新版澎湃OS OPPO A3 Pro正式…