【力扣34】在排序数组中查找元素的第一个和最后一个位置

目录

力扣题目

[核心思路:用 "找第一个≥目标值" 的二分模板统一边界逻辑](#核心思路:用 “找第一个≥目标值” 的二分模板统一边界逻辑)

代码实现

关键解析


力扣题目

给定非递减排序的整数数组 nums 和目标值 target,需找到 target 在数组中的第一个位置最后一个位置 ;若不存在则返回 [-1, -1],要求时间复杂度为 O(log n)

核心要求:依托排序数组特性,用二分查找高效定位边界,拒绝线性遍历。


核心思路:用 "找第一个≥目标值" 的二分模板统一边界逻辑

二分查找的核心是在有序序列中定位满足条件的第一个位置 。我们只需实现一个通用二分模板 ------查找数组中第一个大于等于目标值的索引 (方法名统一为binarySearch),即可统一解决本题的两个边界问题:

  • 第一个位置 :直接调用**binarySearch** 查找 target,得到第一个≥target的索引;若索引越界或对应值不等于target,说明target不存在。
  • 最后一个位置 :等价于调用**binarySearch** 查找第一个**≥target+1**的索引,再将结果减 1。原因是:非递减数组中,target+1的首个出现位置的前一位,就是target的最后一次出现位置。

上述最后一个位置的转化可以参考以下表格:

你想找的 等价问题(转换思路) 调用 binarySearch 返回的 idx 含义 最终答案(位置或值) 举例 (nums=[1,3,3,5,7])
第一个 >= x 原问题 binarySearch(nums, x) 第一个 >= x 的位置 idx(若越界则无解) x=3 → idx=1(值 3)
第一个 > x 第一个 >= (x+1) binarySearch(nums, x+1) 第一个 >= x+1 的位置 idx(若越界则无解) x=3 → idx=3(值 5)
最后一个 < x 第一个 >= x 的左边 binarySearch(nums, x) 第一个 >= x 的位置 idx - 1(若 idx=0 则无解) x=3 → idx=1,答案 0(值 1)
最后一个 <= x 第一个 > x 的左边 或 第一个 >= x+1 的左边 binarySearch(nums, x+1) 第一个 > x 的位置 idx - 1(若 idx=0 则无解) x=3 → idx=3,答案 2(值 3)

具体讲解可以去灵神的b站进行观看,讲得非常好,这里给出链接

二分查找 红蓝染色法【基础算法精讲 04】_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1AP41137w7/?vd_source=7859431ae70beb55fb9f7e7853845e65


代码实现

java 复制代码
class Solution {
    public int[] searchRange(int[] nums, int target) {
        int start = binarySearch(nums, target);
        // 边界校验:target不存在的情况
        if (start == nums.length || nums[start] != target) {
            return new int[]{-1, -1};
        }
        // 推导最后一个位置
        int end = binarySearch(nums, target + 1) - 1;
        return new int[]{start, end};
    }

    /**
     * 通用二分模板:返回数组中第一个大于等于target的索引
     * @param nums 非递减排序的数组
     * @param target 目标值
     * @return 首个≥target的索引;若所有元素都小于target,返回数组长度
     */
    private int binarySearch(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        while (left <= right) {
            // 避免(left + right)溢出,等价于(left + right) / 2
            int mid = left + (right - left) / 2;
            if (nums[mid] < target) {
                // 目标值在右区间,左边界右移
                left = mid + 1;
            } else {
                // 目标值在左区间,右边界左移
                right = mid - 1;
            }
        }
        return left;
    }
}

关键解析

  • binarySearch 模板:严格实现 "找第一个≥目标值" 的逻辑,循环结束后left即为目标索引,天然处理 "所有元素小于目标值" 的越界场景。
  • 存在性校验:通过start的越界判断和值匹配,直接筛除target不存在的情况。
  • 最后位置推导:借助**binarySearch(nums, target + 1)**的查找结果,一步计算出target的最后位置,无需额外二分。

感兴趣的宝子可以关注一波,后续会更新更多有用的知识!!!

相关推荐
暮冬-  Gentle°1 小时前
C++中的命令模式实战
开发语言·c++·算法
卷福同学3 小时前
【养虾日记】Openclaw操作浏览器自动化发文
人工智能·后端·算法
春日见4 小时前
如何入门端到端自动驾驶?
linux·人工智能·算法·机器学习·自动驾驶
图图的点云库4 小时前
高斯滤波实现算法
c++·算法·最小二乘法
回到原点的码农5 小时前
Spring Data JDBC 详解
java·数据库·spring
gf13211115 小时前
python_查询并删除飞书多维表格中的记录
java·python·飞书
zb200641205 小时前
Spring Boot 实战:轻松实现文件上传与下载功能
java·数据库·spring boot
一叶落4385 小时前
题目:15. 三数之和
c语言·数据结构·算法·leetcode
一勺菠萝丶5 小时前
Flowable + Spring 集成踩坑:流程结束监听器查询历史任务为空 & 获取不到审批意见
java·数据库·spring
jwn9995 小时前
Spring Boot 整合 Keycloak
java·spring boot·后端