题目详解
相关链接
思路
- 用双指针二分法
看完代码随想录之后的想法
我的解法只用了一次二分,找到目标值后再向两边延伸:
TypeScript 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17function searchRange(nums: number[], target: number): number[] {
let left = 0,
right = nums.length - 1
while (left <= right) {
const mid = left + ((right - left) >>> 1)
if (nums[mid] === target) {
left = right = mid
break
}
if(nums[mid] < target) left = mid + 1
else right = mid - 1
}
if (left > right) return [-1, -1]
while (nums[--left] === target) {}
while (nums[++right] === target) {}
return [++left, --right]
}虽然ac了,但是因为最后的遍历寻找边界导致时间复杂度实际是O(n),不符合题目要求的O(log n)
实现过程中遇到的困难
- 边界不好判断
代码
两遍二分法分别寻找左边界和右边界:
TypeScript 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29function searchRange(nums: number[], target: number): number[] {
if (!nums.length) return [-1, -1]
const leftBorder = getLeftBorder(nums, target)
const rightBorder = getRightBorder(nums, target)
if (leftBorder === nums.length || rightBorder === 0) return [-1, -1] // target在nums区间两侧
if (rightBorder - leftBorder <= 1) return [-1, -1] // target不存在nums中
return [leftBorder + 1, rightBorder - 1]
}
function getLeftBorder(nums: number[], target: number): number {
let left = 0,
right = nums.length - 1
while (left <= right) {
const mid = left + ((right - left) >>> 1)
if (nums[mid] < target) left = mid + 1
else right = mid - 1
}
return right
}
function getRightBorder(nums: number[], target: number): number {
let left = 0,
right = nums.length - 1
while (left <= right) {
const mid = left + ((right - left) >>> 1)
if (nums[mid] > target) right = mid - 1
else left = mid + 1
}
return left
}时间复杂度:O(logn)
空间复杂度:O(1)
收获
- 二分法的灵活运用