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

算法工具箱之二分查找

二分查找

核心思想:在有序的集合中,通过每次将搜索范围缩小一半来快速定位目标值。​

使用前提:

(1)顺序结构​​:数据结构必须支持通过索引(如数组)或指针(如链表,但链表二分效率低)进行随机访问。

(2)有序性​​:集合中的元素必须是有序的(升序或降序)。这是二分查找能每次排除一半数据的基础。

下面将二分查找分为标准二分查找;查找第一个等于 target 的元素(适用于有重复元素的数组);查找最后一个等于 target 的元素;查找第一个大于等于 target 的元素(可用于插入位置);查找第一个大于 target 的元素为大家讲清楚二分查找这一种算法。

(1)标准二分查找:(时间复杂度:​​O(log n)​​,空间复杂度:​​O(1)​​。)

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

这一题是标准二分查找的例题,我们需要先定义left和right指向数组的两端,再定义mid变量来求出每次数组的中间元素的下标。因为数组的元素是递增的,所以当数组中间的元素大于目标值时,我们往左收缩,反之,我们向右收缩。当left与right错开时,整个数组中就没有这个元素,返回-1。

(2)查找第一个与最后一个等于target的位置

class Solution {
public:vector<int> searchRange(vector<int>& nums, int target) {if(nums.size() == 0){return {-1,-1};}   int begin = 0;int left = 0;int right = nums.size() - 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};}else{begin = left;}left = 0;right = nums.size() - 1;while(left < right){int mid = left + (right - left + 1)/2;if(nums[mid] > target){right = mid - 1;}else{left = mid;}}return {begin,right};}
};

算法思路:⽤的还是⼆分思想,就是根据数据的性质,在某种判断条件下将区间⼀分为⼆,然后舍去其中⼀个 区间,然后再另⼀个区间内查找。

算法步骤:

查找左边界:找到第一个等于target的值。

当nums[mid] < target时,说明目标在右侧,所以让left = mid + 1;当nums[mid] >= target时,说明目标在左侧或者当前位置,所以让right = mid。当left == right程序循环终止。若nums[left] != target时,即不存在target值,返回{-1,-1},若存在则把left值储存在begin中。

查找右边界:找到最后一个等于target的值

也是类似的道理,不过mid计算时要向上取整,避免死循环。

(3)查找第一个大于等于target值的元素。

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

核心思想:如果找到目标值直接返回right值,如果没找到则返回right + 1。

使用的方法与前面的二分查找类似。

时间复杂度为O(log n),空间复杂度O(1)。

http://www.dtcms.com/a/545608.html

相关文章:

  • undefined reference to `cJSON_AddStringToObject‘
  • 仓颉语言中TreeMap红黑树结构的实现与优化
  • Rust 的构建系统和包管理器
  • AI驱动嵌入式软件全链路变革:从芯片到系统的深度智能重构
  • 怎么修改网站域名推广网站排行榜
  • 靠谱的电磁阀维护保养
  • 【自动化测试函数 (下)】Web自动化攻坚:应对加载等待、浏览器导航与无头模式的自动化脚本艺术
  • 正向代理工具
  • 攀枝花建设工程有限责任公司网站中国兰州网
  • Kubernetes 部署
  • 网站建设投标人资质要求wordpress邮箱如何解析
  • 鞍山商城网站建设运城手机网站制作
  • 【GitLab/CD】前端 CD
  • 做简报的网站竹制品网站怎么做
  • Kafka使用-Consumer
  • 诸暨网站建设怎么建立微网站?
  • 【Docker】【1.docker常用命令总结】
  • 深圳的网站建设公司的外文名是wordpress异步加载
  • 创客匠人2025万人高峰论坛:如何融合创始人IP与AI?
  • Linux中完成根文件系统的最终准备和切换prepare_namespace函数的实现
  • A800 部署 Qwen2-VL-8B-Instruct 完整指南
  • rust:第一个程序HelloWorld
  • 给新公司建网站用代理访问永久域名
  • 启动Hana失败 FAIL: process hdbdaemon HDB Daemon not running
  • iOS 26 内存占用监控 多工具协同下的性能稳定性分析实战
  • Kubernetes service管理
  • 布吉企业网站建设百度网站两两学一做心得体会
  • 深入仓颉(Cangjie)编程语言:循环的革命——从“命令式”操控到“声明式”安全迭代
  • 画出网站和目录结构图wordpress 自定义表
  • linux gpio errno EBUSY问题举例分析