给你一个按照非递减顺序排列的整数数组nums,和一个目标值target。请你找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值target,返回[-1, -1]。
你必须设计并实现时间复杂度为O(log n)的算法解决此问题。
示例:
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]
/**
* @description: 二分查找 TC:O(logn) SC:O(1)
* @author: JunLiangWang
* @param {*} nums 输入数组
* @param {*} target 目标值
* @return {*}
*/
function binarySearch(nums,target)
{
/**
* 该方案使用二分查找的方法:
*
* 对于查找元素的第一个位置,我们首先利用二分查找找到元素(设此时索引为middle)
* 并记录该位置为元素的第一个位置,此时我们不知道middle前是否还存在该元素,因
* 此继续利用二分查找区间[left,middle-1]中的元素,并重复上述过程,直至比对完
* 数组元素为止。
*
* 对于查找元素的最后一个位置,我们首先利用二分查找找到元素(设此时索引为middle)
* 并记录该位置为元素的最后一个位置,此时我们不知道middle后是否还存在该元素,因
* 此继续利用二分查找区间[middle+1, right]中的元素,并重复上述过程,直至比对完
* 数组元素为止。
*/
// 初始化元素第一个位置以及最后一个位置为-1,
let firstIndex=-1,lastIndex=-1;
/**
* @description: 二分查找元素
* @author: JunLiangWang
* @param {*} isFindFirst 是否查找元素的第一个位置,
* 否则则为查找元素最后一个位置
* @return {*}
*/
function binarySearchMethods(isFindFirst)
{
// 初始化左指针为首个元素,右指针为最后一个元素
let left=0,right=nums.length-1;
// 当左指针超出右指针证明比对完成数组所有元素,此时跳出循环
while(left<=right)
{
// 计算中间索引
let middle=Math.floor((left+right)/2);
// 当中间索引处值等于target
if(nums[middle]==target)
{
// 如果是查找元素的第一个元素,更新第一个位置值(firstIndex)
// 为中间索引(middle),但我们不知middle前是否还存在相同元素
// 因此则需要在区间[left,middle-1]继续重复该步骤,直至不满
// 足循环条件位置
if(isFindFirst)
{
firstIndex=middle;
right=middle-1;
}
// 否则则是查找元素的最后一个位置,此时更新最后一个位置值
// (lastIndex)为中间索引(middle),但我们不知middle后是否
// 还存在相同元素,因此则需要在区间[middle+1,right]继续
// 重复该步骤,直至不满足循环条件位置
else
{
lastIndex=middle;
left=middle+1
}
}
// 当middle处值大于target,由于nums是单调递增的,因此可
// 以得target是不在区间[middle,right]中的,因此我们在区
// 间[left,middle-1]继续查找即可
else if(nums[middle]>target)right=middle-1;
// 反之,我们则在[middle+1,right]继续查找即可
else left=middle+1;
}
}
// 利用二分查找元素第一个位置
binarySearchMethods(true);
// 利用二分查找元素得最后一个位置
binarySearchMethods(false);
// 返回结果
return [firstIndex,lastIndex];
}