每天学习一点算法 2026/03/25
题目:在排序数组中查找元素的第一个和最后一个位置
给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。
-
直接利用 JS 的 api 取就行了
typescriptfunction searchRange(nums: number[], target: number): number[] { return [nums.findIndex(item => item === target), nums.findLastIndex(item => item === target)] }; -
通用的方法肯定就是遍历查找,因为是已经排序好的数组,我们利用二分查找是最快的。
正常二分法查找一个元素就是,两个指针分别指向数组两端,然后取中间值跟目标值作比较,如果中间值大于目标值表示目标值在左侧区间,否则在右侧区间。
但是这个我们要思考如何找到最左侧和最右侧的目标值。
首先边界是两个指针相遇:
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继续搜索,最终就会找到最右侧的目标值(最终遍历结束的时候上一个中间节点值一定就是最右侧目标值的下一个元素)。最后就是还要考虑找不到目标值的情况。
typescriptfunction 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)
- 如果