题意
一个有序序列,有可能这个序列旋转过,例如:
序列1,2,3,4,5,6
旋转一下,可能为3,4,5,6,1,2
找出 target 出现的位置,序列中的数不重复
思路
如果是普通的有序数列,直接二分即可得出答案,但是这个有序序列可能会旋转过,所以说在二分过程中需要判断一些条件,在分析之前,需要先知道,例如:3,4,5,6,1,2
,将旋转后左边的3,4,5,6
成为
A
集合,将旋转后右边的1,2
成为
- 当前点比
target 大
-
target
比最左边的数小,说明要找的数在B集合中
- 当前点比最左边的数小,说明当前点在B集合中
这时候需要缩小右指针 - 当前点比最左边的数大,说明当前点在A集合中
这时候需要增大左指针
- 当前点比最左边的数小,说明当前点在B集合中
-
target
比最左边的数大,说明要找的数在A集合中
无论当前点在哪个集合中,都需要增大右指针
- 当前点比
target
小
-
target
比最左边的数小,说明要找的数在B集合中
无论当前点在哪个集合,都需要减小左指针 -
target
比最左边的数大,说明要找的数在A集合中
- 当前点比最左边的数小,说明当前点在B集合中
这时候需要缩小右指针 - 当前点比最左边的数大,说明当前点在A集合中
这时候需要增大左指针
- 当前点比最左边的数小,说明当前点在B集合中
-
target
比最左边的数小,说明要找的数在B集合中
代码
class Solution { public: int search(vector<int>& nums, int target) { size_t len = nums.size(); if(len == 0) return -1; size_t left = nums[0]; size_t right = nums[len - 1]; int l = 0, r = len - 1; while(l < r){ int mid = (l + r) / 2; if(nums[mid] > target){ if(target < left){ if(nums[mid] < left){ r = mid - 1; } else{ l = mid + 1; } } else { r = mid - 1; } } else if(nums[mid] < target){ if(target < left){ l = mid + 1; } else { if(nums[mid] < left){ r = mid - 1; } else{ l = mid + 1; } } } else{ l = mid; break; } } if(nums[l] == target) return l; else return -1; } };
-
target
比最左边的数小,说明要找的数在B集合中