【算法拾光】二分查找|二分查找 + 再排序数组中查找元素的第一个和最后一个位置

标签:二分查找、左边界二分、右边界二分、LeetCode 704 / LeetCode 34 区间规范:统一使用 左闭右闭 left, right 写法,工程、面试最稳,减少边界 bug


一、LeetCode 704 二分查找704. 二分查找 - 力扣(LeetCode)

1. 题目分析

题目 :给定一个升序排列、无重复元素的整型数组 nums 和目标值 target。如果数组中存在目标值,返回它的下标;不存在则返回 -1。 已知条件 :数组有序、元素不重复 需求 :快速定位目标,不暴力遍历 暴力缺点:O (n),数据量大时很慢;二分可以做到 O (log n)

2. 算法原理(分步)

二分核心思想:有序数组可以不断折半,排除一半不可能的区间

  1. 定义查找区间 [left, right],左端点 left = 0,右端点 right = nums.size()-1
  2. 循环条件:left <= right(左闭右闭,区间有效才循环)
  3. 取中间下标 mid = left + (right - left) / 2,规避 left+right 溢出
  4. 比较 nums[mid] 和 target:
    • nums[mid] == target:找到目标,直接返回 mid
    • nums[mid] < target:目标在右边区间,更新 left = mid + 1(mid 已经比对过,不需要再包含)
    • nums[mid] > target:目标在左边区间,更新 right = mid - 1
  5. 循环结束,区间空了,说明不存在 target,返回 - 1

3. 代码编写

cpp 复制代码
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){
                return mid;
            }else if(nums[mid] < target){
                left = mid + 1;
            }else{
                right = mid - 1;
            }
        }
        return -1;
    }
};

二、LeetCode 34 在排序数组中查找元素的第一个和最后一个位置34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)

1. 题目分析

题目 :升序整型数组(允许元素重复),给目标值 target,找出目标在数组里第一次出现的下标 和 最后一次出现的下标 ;不存在返回 [-1, -1] 难点 :数组有重复!普通二分找到一个就退出,无法拿到左右边界。 举例 :nums = [5,7,7,8,8,10], target=8,答案是 [3,4] 需求拆解:

  • 子问题 1:二分找左边界:等于 target 的最靠左位置
  • 子问题 2:二分找右边界:等于 target 的最靠右位置

2. 算法原理(分步)

依然使用左闭右闭 left, right,和 704 保持一套逻辑,方便记忆

找左边界逻辑
  1. 初始化 left=0,right=nums.size()-1,答案 res=-1(默认不存在)
  2. 循环 left <= right
  3. 算出 mid,对比:
    • nums[mid] == target:先记录当前 mid 为候选答案 ,但不返回!继续向左搜索,尝试找更早出现的 target → right = mid - 1
    • nums[mid] < target:目标在右侧 → left = mid + 1
    • nums[mid] > target:目标在左侧 → right = mid - 1
  4. 循环结束,res 就是左边界,没找到维持 - 1
找右边界逻辑
  1. 初始化 left=0,right=nums.size()-1,答案 res=-1
  2. 循环 left <= right
  3. 算出 mid,对比:
    • nums[mid] == target:先记录当前 mid 为候选答案 ,不返回!继续向右搜索,尝试找更晚出现的 target → left = mid + 1
    • nums[mid] < target:目标在右侧 → left = mid + 1
    • nums[mid] > target:目标在左侧 → right = mid - 1
  4. 循环结束,res 就是右边界
主函数逻辑

分别调用获取左边界、右边界两个函数,组装成 vector 返回。

3. 代码编写

cpp 复制代码
class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int leftBound = getLeftBound(nums, target);
        int rightBound = getRightBound(nums, target);
        return {leftBound, rightBound};
    }

    // 获取左边界:第一个等于target的下标
    int getLeftBound(vector<int>& nums, int target){
        int left = 0;
        int right = nums.size() - 1;
        int res = -1;
        while(left <= right){
            int mid = left + (right - left) / 2;
            if(nums[mid] == target){
                res = mid;
                right = mid - 1;
            }else if(nums[mid] < target){
                left = mid + 1;
            }else{
                right = mid - 1;
            }
        }
        return res;
    }

    // 获取右边界:最后一个等于target的下标
    int getRightBound(vector<int>& nums, int target){
        int left = 0;
        int right = nums.size() - 1;
        int res = -1;
        while(left <= right){
            int mid = left + (right - left) / 2;
            if(nums[mid] == target){
                res = mid;
                left = mid + 1;
            }else if(nums[mid] < target){
                left = mid + 1;
            }else{
                right = mid - 1;
            }
        }
        return res;
    }
};

三、两篇对比总结

表格

题目 数组特点 命中 target 行为 作用
704 普通二分 有序无重复 直接 return 判断是否存在,返回任意一个位置
34 边界二分 有序可重复 记录答案,继续向一侧压缩区间 找左 / 右边界

核心口诀:有序才能二分;普通二分找到就走,边界二分找到不松手,往一边挤!

相关推荐
文丑颜不良啊41 分钟前
LeetCode76~100题目解析
java·leetcode
零基础1231 小时前
基于模型的强化学习与不基于模型的强化学习:核心区别与实战选择
python·算法
罗西的思考12 小时前
【Agentic RL】Dressage Staleness 控制深度分析
人工智能·算法·机器学习
quaer12 小时前
弗洛伊德算法--判圈法寻找环的入口O(n) O(1)
数据结构·算法
文丑颜不良啊14 小时前
LeetCode51~75题目解析
leetcode
高晶14 小时前
无乘法器实现LC二阶滤波器:基于移位运算的快速算法与四种精度推导
算法·设计模式·程序员
ysbfsy14 小时前
大数计算思路
算法
高晶14 小时前
主从自动分配算法:平均值乘以设备数一半的选举基准值解析
算法·设计模式·程序员
学电子她就能回来吗14 小时前
LeetCode Hot 100|普通数组专题学习笔记(零基础版)
笔记·算法·leetcode