难度:中等
题目:
给你一个按照非递减顺序排列的整数数组 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]
提示:
0 <= nums.length <= 105
-109 <= nums[i] <= 109
nums 是一个非递减数组
-109 <= target <= 109
解题思路:
【思路】要找的就是数组中第一个等于target的位置(l)和最后一个等于target的位置(r)
1、先找出第一个等于target的位置,其中的关键点是:
right = middle - 1 // 这一步是关键、很关键的一步;缩小right的值,这样中间值middle就会缩小;
if (nums[middle] === target) {
l = middle
right = middle - 1 // 这一步是关键、很关键的一步;缩小right的值,这样中间值middle就会缩小;
}
2、找出最后一个等于target的位置,其中的关键点是:
left = middle + 1 // 这一步是关键、很关键的一步;增加left的值,这样中间值middle就会增大;
if (nums[middle] === target) {
r = middle
left = middle + 1 // 这一步是关键、很关键的一步;增加left的值,这样中间值middle就会增大;
}
JavaScript实现:
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var searchRange = function (nums, target) {
let left = 0
let right = nums.length - 1
let l = -1
let r = -1
// 找出第一个target下标
while (left <= right) {
let middle = left + ((right - left) >> 1)
if (nums[middle] === target) {
l = middle
right = middle - 1 // 这一步是关键、很关键的一步;缩小right的值,这样中间值middle就会缩小;
} else if (nums[middle] > target) {
right = middle - 1
} else if (nums[middle] < target) {
left = middle + 1
}
}
// 找到最后一个等于target的下标
left = 0
right = nums.length - 1
while (left <= right) {
let middle = left + ((right - left) >> 1)
if (nums[middle] === target) {
r = middle
left = middle + 1 // 这一步是关键、很关键的一步;增加left的值,这样中间值middle就会增大;
} else if (nums[middle] > target) {
right = middle - 1
} else if (nums[middle] < target) {
left = middle + 1
}
}
return [l, r]
}
tips: 要确保在nums[middle]===target时,找第一个和最后一个时都能够找到最端部