一、题目描述
二、解题思路
要求在
的时间复杂度内确定序列里是否存在这个数字,只能采用二分法
从旋转的方式可以看出,是把较大的那一半放到前面来了,从而导致原序列区间有序,我们可以确定这个区间的分割点,然后在两个区间内二分查找。
这种方法一定可以把原序列分成有序的一半和不一定有序的另一半。
但是这样有个问题,二分查找需要保证原序列递增有序,那我们怎么判断传入的区间序列是否为区间有序?答案是比较区间首尾元素大小关系,如果首大尾小,就不是有序序列,这个关系也可以用在算法的开头,以排除原序列本身就有序的情况。
特殊情况的排除:如果序列为空,直接返回-1
由此,我们得出:
- 首先根据首尾大小关系判断初始序列是否有序,若有序,直接二分查找初始序列
- 选定序列中点为分割点,将序列分割为左右两部分
- 如果左序列有序,右序列无序,那么现在左序列里二分查找,找到了直接返回,否则对把序列的起点更新为右序列的起点,从而将序列长度缩短一半,在右序列里重复上述过程
- 如果左序列无序,右序列有序,那么现在右序列里二分查找,找到了直接返回,否则对把序列的起点更新为左序列的终点,从而将序列长度缩短一半,在左序列里重复上述过程
- 如果刚好分割点把序列分割成有序的两段,在有序的两段里分别进行二分查找,找不到返回
-1
,否则返回找到的位置
三、解题代码
非递归
class Solution {
public:
int search(vector<int>& nums, int target) {
if(!nums.size()) return -1;
int left = 0, right = nums.size() - 1;
while(left <= right){
int loc;
if(nums[left] <= nums[right])
return SearchInA_SortedArray(nums, left, right, target, loc) ? loc : -1;
int pivotpos = (left + right) / 2;
if(nums[pivotpos + 1] >= nums[right] && nums[left] <= nums[pivotpos])
if(SearchInA_SortedArray(nums, left, pivotpos, target, loc))
return loc;
else
left = pivotpos + 1;
else if(nums[pivotpos + 1] <= nums[right] && nums[left] >= nums[pivotpos])
if(SearchInA_SortedArray(nums, pivotpos + 1, right, target, loc))
return loc;
else
right = pivotpos;
else if(nums[pivotpos + 1] <= nums[right] && nums[left] <= nums[pivotpos]){
int tmpl, tmpr;
if(SearchInA_SortedArray(nums, left, pivotpos, target, tmpl) || SearchInA_SortedArray(nums, pivotpos + 1, right, target, tmpr))
return max(tmpl, tmpr);
return -1;
}
}
return -1;
}
private:
bool SearchInA_SortedArray(vector<int>& nums, int left, int right, int target, int& loc){
if(left <= right){
loc = -1;
while(left <= right){
int mid = (left + right) / 2;
if(nums[mid] == target){
loc = mid;
return true;
}
else if(nums[mid] < target) left = mid + 1;
else right = mid - 1;
}
}
return false;
}
};
递归
class Solution {
private:
int Search(vector<int>& nums, int l, int h, int target) {
if(l > h)
return -1;
int m = (l + h) >> 1;
if(nums[m] == target) return m;
if(nums[m] < nums[h]){
if(nums[m] < target && target <= nums[h])
return Search(nums, m + 1, h, target);
else
return Search(nums, l, m - 1, target);
}
else{
if(nums[l] <= target && target < nums[m])
return Search(nums, l, m - 1, target);
else
return Search(nums, m + 1, h, target);
}
}
public:
int search(vector<int>& nums, int target) {
return Search(nums, 0, nums.size() - 1, target);
}
};
三、运行结果
非递归
递归