思路
- 数组有一个结点出现乱序,但是这个结点被二分时,还有部分为有序
- 哪部分有序?——nums[mid]大于nums[0]代表左边有序,小于nums[0]代表右边有序
- 利用有序的半部分来判断target在左边还是右边
- 要是在右边,右边的乱序被二分后,又出现有序的部分…
代码
class Solution {
public:
int search(vector<int>& nums, int target) {
int n = (int)nums.size();
if (!n)
return -1;
if (n == 1)
return nums[0] == target ? 0 : -1;
int l = 0, r = n - 1;
while (l <= r) {
int mid = (l + r) / 2;
if (nums[mid] == target) return mid;
if (nums[0] <= nums[mid]) {
if (nums[0] <= target && target < nums[mid])
r = mid - 1;
else
l = mid + 1;
}
else {
if (nums[mid] < target && target <= nums[n - 1])
l = mid + 1;
else
r = mid - 1;
}
}
return -1;
}
};
解析
例如 输入为 [4,5,6,7,0,1,2] 6
7 大于 4
6 属于 [4,7] right=2
5 大于 4
6 不属于 [4,5] left=2
找到 6
可以看到4本为中间值,
**那么mid大于它的证明该部分的左边为有序,如果小于它证明该部分右边有序**
那么当nums[0]==nums[mid]时呢? 此时认为左边是有序的
或者可以看到2本为中间值
**那么mid大于它的证明该部分的左边为有序,如果小于它的证明该部分右边有序**
那么当num[n-1]==nums[mid]时呢? 此时认为右边是有序的
也就是说 nums[0] <= nums[mid] 可以改成 nums[n-1] < nums[mid]