一、题目
给定一个按照升序排列的整数数组 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]
作者:力扣 (LeetCode) 链接:leetcode-cn.com/leetbook/re…
来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
二、思路
暴力解法
- 暴力解法
- 返回目标值在数组中的开始位置和结束位置
- 在数组不存在目标值的情况下,返回[-1,-1]
- 因此默认开始位置和结束位置为left = -1, right = -1
- 两个for循环,第一个for循环找left,找到后退出,
- 第二个for循环找right,找到后退出循环
- 找到没有找到,最后都return [left, right]
二分查找
- 根据暴力解法可知,首先要找到开始位置lindex值,
- 再查找rindex值
- 定义len = nums.length, left = 0, right = len - 1, result = nums.length
- 循环条件是left <= right
- 中间值: mid = Math.floor((left + right)/ 2)
- 这里可以思考一个问题,什么时候能拿到lindex值,当nums[mid]>= target时,就拿到了lindex
- 满足条件 right = mid -1 , result = mid
- 否则left = mid + 1,最后当条件不满足时,返回结果
- 这是思考rindex的求值方式,其实当nums[mid]> target时,mid - 2 就是rindex的坐标了
- 由于两个高度相似,因此提取代码
- 定义coordinate = (nums, target, seat)
- 最后还要做下判断
- 如果nums[lindex] === target为真,那么就是有开始位置和结束位置
- 否则返回[-1, -1]
三、代码
暴力解法的代码
let searchRange = function(nums, target) {
/**
* 暴力解法
* 返回目标值在数组中的开始位置和结束位置
* 在数组不存在目标值的情况下,返回[-1,-1]
* 因此默认开始位置和结束位置为left = -1, right = -1
* 两个for循环,第一个for循环找left,找到后退出,
* 第二个for循环找right,找到后退出循环
* 找到没有找到,最后都return [left, right]
* **/
let len = nums.length, left = -1, right = -1
for(let i = 0; i < len; i++) {
if (nums[i] == target) {
left = i
break
}
}
for(let i = len; i > -1; i--) {
if (nums[i] == target) {
right = i
break
}
}
return [left, right]
}
二分查找解法
// let nums = [5,7,7,8,8,10], target = 8
// let nums = [5,7,7,8,8,10], target = 6
// let nums = [], target = 0
let nums = [1], target = 1
// let nums = [1,2], target = 1
// let nums = [3,3,3], target = 3
let searchRange = function(nums, target) {
/**
* 二分查找
* 根据暴力解法可知,首先要找到开始位置lindex值,
* 再查找rindex值
* 定义len = nums.length, left = 0, right = len - 1, result = nums.length
* 循环条件是left <= right
* 中间值: mid = Math.floor((left + right)/ 2)
* 这里可以思考一个问题,什么时候能拿到lindex值,当nums[mid]>= target时,就拿到了lindex
* 满足条件 right = mid -1 , result = mid
* 否则left = mid + 1,最后当条件不满足时,返回结果
* 这是思考rindex的求值方式,其实当nums[mid]> target时,mid - 2 就是rindex的坐标了
* 由于两个高度相似,因此提取代码
* 定义coordinate = (nums, target, seat)
* 最后还要做下判断
* 如果nums[lindex] === target为真,那么就是有开始位置和结束位置
* 否则返回[-1, -1]
*
* */
let lindex = coordinate(nums, target, 'left')
let rindex = coordinate(nums, target, 'right') - 1
if (nums[lindex] === target) return [lindex, rindex]
return [-1, -1]
}
const coordinate = (nums, target, seat) => {
let len = nums.length, left = 0, right = len - 1, result = nums.length
while(left <= right) {
const mid = Math.floor((left + right) / 2)
const midNum = nums[mid]
const state = seat === 'left' ? (midNum >= target):(midNum > target)
if (state) {
right = mid - 1
result = mid
} else {
left = mid + 1
}
}
return result
}
searchRange(nums, target)