题目
给定一个经过旋转的升序数组和目标值,返回目标值下标;若不存在,返回 -1。
题目分析
这题虽然是二分,但难点不在传统的“比大小缩区间”,而在于你要先判断:
- 左半边是否有序
- 右半边是否有序
因为旋转之后,至少有一边仍然保持有序。
方法一:直觉解法
暴力扫描当然可以做,但这题的价值就在于练习“带条件判断的二分查找”。
方法二:优化思路
每次取 mid 后:
- 如果
nums[left] <= nums[mid],说明左半边有序 - 否则右半边有序
再根据 target 是否落在有序区间里,决定保留哪一半。
Go 实现
1func search(nums []int, target int) int {
2 left, right := 0, len(nums)-1
3 for left <= right {
4 mid := left + (right-left)/2
5 if nums[mid] == target {
6 return mid
7 }
8
9 if nums[left] <= nums[mid] {
10 if nums[left] <= target && target < nums[mid] {
11 right = mid - 1
12 } else {
13 left = mid + 1
14 }
15 } else {
16 if nums[mid] < target && target <= nums[right] {
17 left = mid + 1
18 } else {
19 right = mid - 1
20 }
21 }
22 }
23 return -1
24}
复杂度分析
- 时间复杂度:
O(log n) - 空间复杂度:
O(1)
易错点
- 判断哪边有序时,不要忘记带等号
- 条件区间要和保留区间严格对应,否则很容易丢答案
我的复盘
这题让我意识到:很多“变种二分”并不是新模板,而是在二分骨架上额外叠一层区间语义判断。