题目
- 旋转排序数组:将严格单调递增数组 [ k , n − 1 ] [k,n-1] [k,n−1] 的子序列放到开头。例如, [ 0 , 1 , 2 , 4 , 5 , 6 , 7 ] [0,1,2,4,5,6,7] [0,1,2,4,5,6,7] 在下标 3 3 3 处经旋转后可能变为 [ 4 , 5 , 6 , 7 , 0 , 1 , 2 ] [4,5,6,7,0,1,2] [4,5,6,7,0,1,2].
- 要求以 O ( l o g N ) O(logN) O(logN) 的复杂度返回旋转排序后的数组中值为 t a r g e t target target 的索引,没有则返回 − 1 -1 −1.
关键点
- O ( l o g N ) O(logN) O(logN) 复杂度(二分查找)、
- 旋转排序后的数组如何进行二分查找
思路
- 正常使用二分查找,关键在于如何更新查找区间的左右边界
- 对于正常的有序数组(假设递增),初始化左右边界
p
l
,
p
r
pl,pr
pl,pr 为
0
,
n
−
1
0, n-1
0,n−1。判断
m
i
d
=
i
n
t
(
(
p
l
+
p
r
)
/
2
)
mid=int((pl+pr)/2)
mid=int((pl+pr)/2) 与
t
a
r
g
e
t
target
target 的大小关系:
- 若 n u m s [ m i d ] = = t a r g e t , r e t u r n nums[mid] == target, return nums[mid]==target,return
- 若 n u m s [ m i d ] < t a r g e t , p l = m i d + 1 nums[mid] < target, pl=mid+1 nums[mid]<target,pl=mid+1
- 若 n u m s [ m i d ] > t a r g e t , p r = m i d − 1 nums[mid] > target, pr=mid-1 nums[mid]>target,pr=mid−1
- 对于本题的旋转排序数组,初始化左右边界
p
l
,
p
r
pl,pr
pl,pr 为
0
,
n
−
1
0, n-1
0,n−1,
m
i
d
=
i
n
t
(
(
p
l
+
p
r
)
/
2
)
mid=int((pl+pr)/2)
mid=int((pl+pr)/2),
m
i
d
mid
mid 将
p
l
pl
pl 到
p
r
pr
pr 的数组分为了两半,其中必有一半是有序的:
- 若
[
p
l
,
m
i
d
]
[pl, mid]
[pl,mid] 有序:
- 若 t a r g e t target target 在 [ p l , m i d ] [pl, mid] [pl,mid] 中, p r = m i d − 1 pr=mid-1 pr=mid−1
- 若不在, p l = m i d + 1 pl=mid+1 pl=mid+1
- 若
[
m
i
d
,
p
r
]
[mid, pr]
[mid,pr] 有序:
- 若 t a r g e t target target 在 [ m i d , p r ] [mid, pr] [mid,pr] 中, p l = m i d + 1 pl=mid+1 pl=mid+1
- 若不在, p r = m i d − 1 pr=mid-1 pr=mid−1
- 若
[
p
l
,
m
i
d
]
[pl, mid]
[pl,mid] 有序:
- 如何判断
[
p
l
,
m
i
d
]
[pl,mid]
[pl,mid] 和
[
m
i
d
,
p
r
]
[mid,pr]
[mid,pr] 哪个有序
- 比较
n
u
m
s
[
m
i
d
]
nums[mid]
nums[mid] 和
n
u
m
s
[
0
]
nums[0]
nums[0] 的大小
- 若 n u m s [ 0 ] < n u m s [ m i d ] nums[0] < nums[mid] nums[0]<nums[mid] 则 [ 0 , m i d ] [0, mid] [0,mid] 必定有序,进而可以得到 [ p l , m i d ] [pl, mid] [pl,mid] 必定有序
- 若 n u m s [ 0 ] > n u m s [ m i d ] nums[0] > nums[mid] nums[0]>nums[mid] 则 [ 0 , m i d ] [0, mid] [0,mid] 必定无序,进而可以得到 [ m i d , n − 1 ] [mid, n-1] [mid,n−1] 必定有序,进一步得到 [ m i d , p r ] [mid, pr] [mid,pr] 必定有序
- 比较
n
u
m
s
[
m
i
d
]
nums[mid]
nums[mid] 和
n
u
m
s
[
0
]
nums[0]
nums[0] 的大小
代码
class Solution {
public:
int search(vector<int>& nums, int target) {
// O(N)
// int n = nums.size();
// for(int i = 0; i < n; i++){
// if(nums[i] == target){
// return i;
// }
// }
// return -1;
// O(logN)
int n = nums.size();
int pl = 0, pr = n-1;
while(pl <= pr && pl >= 0 && pr <= n-1){
int mid = (pl+pr)/2;
if(nums[mid] == target){
return mid;
}
if(nums[mid] >= nums[0]){
if(nums[0] <= target && target < nums[mid]){
pr = mid - 1;
}
else{
pl = mid + 1;
}
}
else{
if(nums[mid] < target && target <= nums[pr]){
pl = mid + 1;
}
else{
pr = mid - 1;
}
}
}
return -1;
}
};