【 每天学习一点算法 2026/03/25】在排序数组中查找元素的第一个和最后一个位置

每天学习一点算法 2026/03/25

题目:在排序数组中查找元素的第一个和最后一个位置

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]。

你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

  1. 直接利用 JS 的 api 取就行了

    typescript 复制代码
    function searchRange(nums: number[], target: number): number[] {
        return [nums.findIndex(item => item === target), nums.findLastIndex(item => item === target)]
    };
  2. 通用的方法肯定就是遍历查找,因为是已经排序好的数组,我们利用二分查找是最快的。

    正常二分法查找一个元素就是,两个指针分别指向数组两端,然后取中间值跟目标值作比较,如果中间值大于目标值表示目标值在左侧区间,否则在右侧区间。

    但是这个我们要思考如何找到最左侧和最右侧的目标值。

    首先边界是两个指针相遇:left <= right

    假设我们取 Math.floor((left + right) / 2)

    • 如果 nums[mid] > target,表示目标值在这个中间值的左侧,需要使 right = mid - 1继续搜索
    • 如果 nums[mid] < target,表示目标值在这个中间值的右侧,需要使 left = mid + 1继续搜索
    • 如果nums[mid] == target,表示这就是目标值了。

    如果我们要继续搜索左侧还有没有目标值是不是得继续移动右指针使 right = mid - 1继续搜索,最终就会找到最左侧的目标值(最终遍历结束的时候上一个中间节点值一定就是最左侧目标值)。

    如果我们要继续搜索右侧还有没有目标值是不是得继续移动左指针使 left = mid + 1继续搜索,最终就会找到最右侧的目标值(最终遍历结束的时候上一个中间节点值一定就是最右侧目标值的下一个元素)。

    最后就是还要考虑找不到目标值的情况。

    typescript 复制代码
    function searchRange(nums: number[], target: number): number[] {
      function findIndex (nums: number[], target: number, isLower: boolean) {
        let left = 0, right = nums.length - 1
        let index = nums.length // 我们只在右节点移动时做了下标赋值操作,所以起始下标要放在 nums.length 处
        while (left <= right) {
          const mid = Math.floor((left + right) / 2)
          // 根据传入的表示确定是找最左侧还是最右侧的目标值
          if (nums[mid] > target || (isLower && nums[mid] >= target)) {
            right = mid - 1
            // 保存当前中间值下标
            index = mid
          } else {
            left = mid + 1
          }
        }
        // 遍历结束 当前 index 为遍历结束的时候上一个中间节点值
        return index
      }
      const res = [-1, 1]
      const leftIndex = findIndex(nums, target, true)
      const rightIndex = findIndex(nums, target, false) - 1
      if (nums[leftIndex] === target && nums[rightIndex] === target) {
        // 确认找到目标值
        res = [leftIndex, rightIndex]
      }
      return res
    };

    题目来源:力扣(LeetCode)

相关推荐
故事和你9119 小时前
洛谷-数据结构1-1-线性表1
开发语言·数据结构·c++·算法·leetcode·动态规划·图论
脱氧核糖核酸__19 小时前
LeetCode热题100——53.最大子数组和(题解+答案+要点)
数据结构·c++·算法·leetcode
脱氧核糖核酸__20 小时前
LeetCode 热题100——42.接雨水(题目+题解+答案)
数据结构·c++·算法·leetcode
王老师青少年编程20 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【线性扫描贪心】:数列分段 Section I
c++·算法·编程·贪心·csp·信奥赛·线性扫描贪心
王老师青少年编程20 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【线性扫描贪心】:分糖果
c++·算法·贪心算法·csp·信奥赛·线性扫描贪心·分糖果
_日拱一卒20 小时前
LeetCode:2两数相加
算法·leetcode·职场和发展
低代码布道师20 小时前
微搭低代码MBA 培训管理系统实战 30——学习卡
学习·低代码·rxjava
py有趣20 小时前
力扣热门100题之零钱兑换
算法·leetcode
南無忘码至尊21 小时前
Unity学习90天 - 第 6天 - 学习协程 Coroutine并实现每隔 2 秒生成一波敌人
学习·unity·c#·游戏引擎
董董灿是个攻城狮21 小时前
Opus 4.7 来了,我并不建议你升级
算法