3.2 二分查找专题:LeetCode 34. 在排序数组中查找元素的第一个和最后一个位置

server/2025/3/18 17:20:00/
1. 题目链接

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


2. 题目描述

给定一个升序排列的整数数组 nums 和一个目标值 target,返回目标值在数组中的起始位置结束位置。若不存在,返回 [-1, -1]
要求:时间复杂度为 O(log n)


3. 示例分析

示例1
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4](第一个 8 在索引 3,最后一个在索引 4)。

示例2
输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]6 不存在)。

暴力枚举法:遍历数组,记录第一个和最后一个匹配的位置。
二分查找:通过两次二分查找分别定位左右边界。


4. 算法思路

两次二分查找

  1. 寻找左边界

    • 初始化 left = 0, right = nums.size() - 1
    • 循环条件 left < right,中间值 mid 向左取整mid = left + (right - left) / 2)。
    • nums[mid] >= target,压缩右边界 right = mid,否则增大左边界 left = mid + 1
    • 最终 left 指向左边界,需检查是否等于 target
  2. 寻找右边界

    • 初始化 left = 0, right = nums.size() - 1
    • 循环条件 left < right,中间值 mid 向右取整mid = left + (right - left + 1) / 2)。
    • nums[mid] <= target,压缩左边界 left = mid,否则减小右边界 right = mid - 1
    • 最终 left 指向右边界,需检查是否等于 target

5. 边界条件与注意事项
  1. 空数组处理:直接返回 [-1, -1]
  2. 越界检查:左边界需验证 left < nums.size(),右边界需验证 right >= 0
  3. 中间值取整方向
    • 左边界查找时,mid 向左取整避免死循环。
    • 右边界查找时,mid 向右取整确保收缩正确性。
  4. 重复元素处理:需确保找到第一个和最后一个匹配位置。

6. 代码实现
class Solution 
{
public:vector<int> searchRange(vector<int>& nums, int target) {if (nums.empty()) return {-1, -1};int left = 0, right = nums.size() - 1;vector<int> ret;// 1.左边 target 第一次出现while(left < right){int mid = left + (right - left) / 2; // 取左边if(nums[mid] >= target) right = mid;// 关键条件:压缩右边界else left = mid + 1;}ret.push_back((left < nums.size() && nums[left] == target) ? left : -1);// 2.右边 target 第一次出现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;}ret.push_back((right >= 0 && nums[left] == target) ? right : -1);return ret;}
};

在这里插入图片描述


暴力枚举法与二分查找法对比图表

对比维度暴力枚举法二分查找
核心思想遍历数组所有元素,记录第一个和最后一个匹配的位置。通过两次二分查找分别定位左右边界,利用数组有序性快速缩小范围。
时间复杂度O(n)(遍历所有元素)。O(log n)(两次二分查找,每次时间复杂度为 O(log n))。
空间复杂度O(1)(无需额外存储)。O(1)(仅需常数变量记录指针)。
实现方式单层循环遍历数组,记录匹配的起始和结束索引。两次独立的二分查找,分别处理左右边界。
适用场景无序数组、小规模数据(n ≤ 100)。有序数组、大规模数据(n ≥ 1e6)。
优点实现简单,不依赖数组有序性。时间复杂度极低,适合处理大规模数据。
缺点数据规模大时性能极差(例如 n=1e6 时需 1e6 次操作)。需处理二分查找的边界条件和中间值取整方向,实现复杂度较高。

http://www.ppmy.cn/server/176010.html

相关文章

SpringBoot + Mybatis Plus 整合 Redis

Redis 在用户管理系统中的典型应用场景 结合你的用户增删改查接口&#xff0c;以下是 Redis 的实用场景和具体实现方案&#xff1a; 场景作用实现方案用户信息缓存减少数据库压力&#xff0c;加速查询响应使用 Spring Cache Redis 注解缓存登录 Token 存储分布式 Session 或…

Unity小框架之单例模式基类

单例模式&#xff08;Singleton Pattern&#xff09;是一种常用的创建型设计模式&#xff0c;其核心目标是确保一个类只有一个实例&#xff0c;并提供一个全局访问点。它常用于需要控制资源访问、共享配置或管理全局状态的场景&#xff08;如数据库连接池、日志管理器、应用配置…

(vue)elementUi中el-upload上传附件之后 点击附件可下载

(vue)elementUi中el-upload上传附件之后 点击附件可下载 handlePreview(file) {console.log(file)const fileUrl https://.../zzy/ file.urlconst a document.createElement(a)a.href fileUrla.download file.namea.style.display none// a.setAttribute(download, file.…

【k8s003】k8s与docker的依赖关系

‌一、早期版本对应关系&#xff08;Kubernetes 1.20 之前&#xff09;‌ ‌Kubernetes 1.13–1.19‌ ‌支持的 Docker 版本范围‌&#xff1a;1.13.1 至 19.03.x‌ ‌说明‌&#xff1a;此阶段 Kubernetes 直接依赖 Docker 作为默认容器运行时&#xff0c;需严格匹配版本以避免…

Linux中安装MySQL

检查是否有MySQL服务并卸载 检查并卸载 在安装MySQL数据库之前&#xff0c;我们需要先检查一下当前Linux系统中&#xff0c;是否安装的有MySQL的相关服务&#xff08;很多linux安装完毕之后&#xff0c;自带了低版本的mysql的依赖包&#xff09;&#xff0c;如果有&#xff0c…

【网络安全 | 漏洞挖掘】$15,000——通过持久token获取个人身份信息(PII)

未经许可,不得转载。 文章目录 绕侧攻击应用程序发现注册流程中的异常token调查token泄露Google Dorking 登场Wayback Machine 的作用影响分析绕侧攻击应用程序 某金融服务平台提供了测试凭据,允许直接登录测试环境。主应用程序包含数百个功能和端点,因此在测试过程中花费了…

课程分享 | 智能网联汽车网络安全测试框架

汽车智能化带来巨大网络安全风险 据公安部2024年1月统计&#xff0c;我国汽车保有量已达3.36亿辆&#xff0c;全国有94座城市汽车保有量超过100万辆。 与此同时&#xff0c;智能网联汽车的发展势头迅猛。2023年我国搭载组合驾驶辅助系统的智能网联乘用车新车销售约950万辆&…

鸿蒙路由 HMrouter 配置及使用一

1、学习链接 HMRouter地址 https://gitee.com/hadss/hmrouter/blob/dev/HMRouterLibrary/README.md 2、工程配置 下载安装 ohpm install hadss/hmrouter 添加编译插件配置 在工程目录下的build-profile.json5中&#xff0c;配置useNormalizedOHMUrl属性为true (我这项目创…