【力扣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的最后位置,无需额外二分。

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

相关推荐
祖力554 小时前
数据结构的基本概念与单向链表(链表数据类型构造、创建、头插、尾插、头删、尾删)
数据结构·链表
大明者省5 小时前
WSL2 Ubuntu22.04 GPU训练环境配置指南
人工智能·算法·计算机视觉
嘻哈∠※6 小时前
0061基于 SpringBoot 的投稿与稿件处理系统设计与实现
java·spring boot·后端
白狐_7987 小时前
408数据结构第8章:排序②——性质对比秒杀、场景选择与外部排序
java·数据结构·算法
zander2587 小时前
LeetCode 84:柱状图中的最大矩形——单调栈如何确定左右边界
java·数据结构·算法
码匠许师傅8 小时前
【C++ 面试真题】聊聊 C++ 的拷贝构造与拷贝赋值
java·c++·面试
Shell运维手记8 小时前
Linux 常用基础命令学习笔记
linux·运维·笔记·学习·算法·github
杨航 AI8 小时前
O(n log n):线性对数原理拆解 这个是排序算法的黄金复杂度之一。
算法·排序算法
船厂电气自动化ai大模型9 小时前
AI大模型与数学 第32课 函数凹凸性与二阶导数:拐点求解、凹凸区间计算(10道二阶导数计算题)
数据结构·人工智能·python·深度学习·算法
旖旎夜光9 小时前
LeetCode 3:无重复字符的最长子串(滑动窗口) —— 题解
数据结构·c++·算法·leetcode·滑动窗口