题目:
给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。
示例 1:
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]
示例 2:
输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]
示例 3:
输入:nums = [], target = 0
输出:[-1,-1]
解析:
由于题目对时间复杂度的限制,在这里使用二分查找的思路更加的方便,这里与二分查找略微不同,需要设置一个index表示向左或者向右的边界情况,index代表了左右边界的索引
具体代码:
javascript
/**
* 在已排序数组中查找目标值的起始和结束位置
* @param {number[]} nums - 已排序的升序数组
* @param {number} target - 要查找的目标值
* @return {number[]} - 返回包含起始和结束位置的数组,如果未找到则返回[-1, -1]
*/
var searchRange = function(nums, target) {
// 查找目标值的左边界(第一次出现的位置)
let left = search(nums, target, true);
// 查找目标值的右边界(最后一次出现的位置)
let right = search(nums, target, false);
// 返回结果数组
return [left, right];
};
/**
* 二分查找辅助函数,用于查找目标值的边界
* @param {number[]} nums - 已排序的升序数组
* @param {number} target - 要查找的目标值
* @param {boolean} isLeft - 标识查找的是左边界(true)还是右边界(false)
* @return {number} - 返回找到的边界索引,未找到则返回-1
*/
function search(nums, target, isLeft) {
// 初始化二分查找的左右指针
let left = 0;
let right = nums.length - 1;
// 初始化结果索引为-1(表示未找到)
let index = -1;
// 二分查找主循环
while (left <= right) {
// 计算中间索引
let mid = Math.floor((left + right) / 2);
if (nums[mid] > target) {
// 中间值大于目标值,在左半部分继续查找
right = mid - 1;
} else if (nums[mid] < target) {
// 中间值小于目标值,在右半部分继续查找
left = mid + 1;
} else {
// 找到目标值,记录当前索引
index = mid;
if (isLeft) {
// 如果是查找左边界,继续在左半部分查找更早出现的位置
right = mid - 1;
} else {
// 如果是查找右边界,继续在右半部分查找更晚出现的位置
left = mid + 1;
}
}
}
// 返回找到的边界索引(如果未找到则为-1)
return index;
}