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

【LeetCode题解】LeetCode 35. 搜索插入位置

【题目链接】
35. 搜索插入位置
【题目描述】
在这里插入图片描述
【题解】
通过题目可以知道这是一道经典的二分查找的题目,对于二分查找的题目,根据需要查找的两个边界点,分为两个不同的模板,如下图所示。
在这里插入图片描述
这道题要求在数组中查找目标值并返回其索引,若目标值不存在,则返回它按顺序插入的位置。因此,它适合使用绿色边界点对应的二分查找模板。
该模板适用于查找最小满足条件的值的场景,常用于定位满足特定条件的最小值或区间的左边界。其核心逻辑是通过不断收缩右边界,最终定位到符合条件的最小值。

其模板如下:

bool check(int x) {/* ... */} // 检查x是否满足某种性质int bsearch_2(int l, int r)
{while (l < r){int mid = l + r >> 1;if (check(mid)) r = mid;else l = mid + 1;}return l;
}

【AC代码】

class Solution {
public:int searchInsert(vector<int>& nums, int target) {int l = 0, r = nums.size();while(l < r) {int mid = l + r >> 1;if(nums[mid] >= target)r = mid;elsel = mid + 1;}return l;}
};

【思考】
1.能否使用红色边界点对应的模板呢?
这道题同样可以用红色边界点对应的模板来解答,只是需要先将问题转化为寻找最后一个小于目标值的元素位置,再通过推导得出插入位置。
该模板的核心是定位最后一个满足条件的位置(即右边界),而原问题实际需要的是第一个大于等于目标值的位置(即左边界)。两者的转化逻辑很明确:插入位置 = 最后一个小于目标值的位置 + 1,而寻找最后一个小于目标值的位置恰好是红色边界点模板的典型应用场景。

其模板如下:

bool check(int x) {/* ... */} // 检查x是否满足某种性质int bsearch_1(int l, int r)
{while (l < r){int mid = l + r + 1 >> 1;if (check(mid)) l = mid;else r = mid - 1;}return l;
}

【AC代码】

class Solution {
public:int searchInsert(vector<int>& nums, int target) {int l = 0, r = nums.size() - 1; while (l < r) {int mid = (l + r + 1) / 2; if (nums[mid] < target) { l = mid;} else {                  r = mid - 1;}}// 循环结束后,l是最后一个可能<target的位置,需判断是否真的满足if (nums[l] < target) {return l + 1; // 存在<target的元素,插入位置为l+1} else {return l;     // 所有元素≥target,插入位置为l(即第一个≥target的位置)}}
};

2.模板的两个边界lr如何确定?
在ac之前,我卡在了一个地方,r一直取的值是r = nums.size() - 1,这导致在测试样例时,示例1和示例2都可以通过,但输入3确报了错。通过调试输出排查后发现,问题的根源在于边界值的设置。
r = nums.size() - 1时,示例1:
l=0,r=3,mid=1,nums[mid]=3,3<target,l=mid+1=1+1=2;l=0,r=3,mid=1,nums[mid]=3,3<target,l=mid+1=1+1=2;l=0,r=3,mid=1,nums[mid]=3,3<target,l=mid+1=1+1=2;
l=2,r=3,mid=2,nums[mid]=5,5≥5,r=2;l=2,r=3,mid=2,nums[mid]=5,5≥5,r=2;l=2,r=3,mid=2,nums[mid]=5,55,r=2;
l=2,r=2,l=2,r=2,l=2,r=2,退出循环,返回l=2,答案正确
r = nums.size() - 1时,示例2:
l=0,r=3,mid=1,nums[mid]=3,3>target,r=1;l=0,r=3,mid=1,nums[mid]=3,3>target,r=1;l=0,r=3,mid=1,nums[mid]=3,3target,r=1;
l=0,r=1,mid=0,nums[mid]=1,1<target,l=mid+1=0+1=1;l=0,r=1,mid=0,nums[mid]=1,1<target,l=mid+1=0+1=1;l=0,r=1,mid=0,nums[mid]=1,1target,l=mid+1=0+1=1;
l=1,r=1,l=1,r=1,l=1,r=1,退出循环,返回l=1,答案正确
r = nums.size() - 1时,示例3:
l=0,r=3,mid=1,nums[mid]=3,3<target,l=mid+1=1+1=2;l=0,r=3,mid=1,nums[mid]=3,3<target,l=mid+1=1+1=2;l=0,r=3,mid=1,nums[mid]=3,3target,l=mid+1=1+1=2;
l=2,r=3,mid=2,nums[mid]=5,5<target,l=mid+1=2+1=3;l=2,r=3,mid=2,nums[mid]=5,5<target,l=mid+1=2+1=3;l=2,r=3,mid=2,nums[mid]=5,5target,l=mid+1=2+1=3;
l=3,r=3,l=3,r=3,l=3,r=3,退出循环,返回l=3,答案错误
通过上述分析可以发现,r = nums.size()的设置确保了搜索区间覆盖所有可能的插入位置,而r = nums.size() - 1会漏掉插入到数组末尾的情况,导致部分测试用例失败。
二分查找的核心是明确搜索区间的定义,并确保区间覆盖所有可能的解

http://www.lryc.cn/news/622703.html

相关文章:

  • Dify实战应用指南(上传需求稿生成测试用例)
  • Jenkins常见问题及解决方法
  • STM32 延时函数详解
  • 343整数拆分
  • 后量子密码算法ML-DSA介绍及开源代码实现
  • 【Qt开发】常用控件(四)
  • 算法提升之树上问题-(tarjan求LCA)
  • 基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
  • MySQL 配置性能优化赛技术文章
  • Win10、Win11电脑之间无法Ping通解决办法
  • 设计模式之【快速通道模式】,享受VIP的待遇
  • Python - 100天从新手到大师:第十一天常用数据结构之字符串
  • OpenCV Python——图像拼接(一)(图像拼接原理、基础知识、单应性矩阵 + 图像变换 + 拼接)
  • redis基本类型之哈希
  • 爬机 验证服务器是否拒绝请求
  • 衡石使用指南嵌入式场景实践之仪表盘嵌入
  • 【Docker项目实战】使用Docker部署Notepad轻量级记事本
  • 《吃透 C++ 类和对象(中):const 成员函数与取地址运算符重载解析》
  • js原生实现手写签名与使用signature_pad库实现手写签名
  • 【Java Web 快速入门】十一、Spring Boot 原理
  • Flutter开发 网络请求
  • Flutter InheritedWidget 详解:从生命周期到数据流动的完整解析
  • Flutter Provider 模式实现:基于 InheritedWidget 的状态管理实现
  • SQL183 近三个月未完成试卷数为0的用户完成情况
  • 力扣(LeetCode) ——142. 环形链表 II(C语言)
  • JavaWeb 30 天入门:第十一天 ——Java 反射机制详解
  • 【环境变量与程序地址空间详解】
  • vue3动态的控制表格列的展示简单例子
  • 从希格斯玻色子到 QPU:C++ 的跨维度征服
  • KingbaseES高可用架构深度解析——从读写分离到异地灾备的全方位守护