题目描述:
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7
might become 4 5 6 7 0 1 2
).
You are given a target value to search. If found in the array return its index, otherwise return -1.
You may assume no duplicate exists in the array.
分析:
题意:给定一个旋转有序非重复数组,一个目标值,查找该值。如果找到,返回对应坐标,否则返回-1。
思路:如果只是一个有序数组,我们可以直接采用普通的二分法。可是现在经过旋转操作,我们也需要对二分法做一些改进。假设数组nums的大小为n,目标值为target,初始化指针left = 0,right = n - 1。
①计算mid = (left + right) >> 1(防止整型数计算溢出的写法),若nums[left]、nums[right]或者nums[mid]等于target,则查找完毕,直接返回对应坐标。
②我们可以看出,对于经过旋转的数组,总可以找到一个i,使得nums[i - 1] > nums[i](原始有序数组除外),此时nums[0→i - 1]、nums[i→n - 1]各自为升序子数组。那么任意选择一个j作为分割点,nums[0→j - 1]、nums[j→n - 1]至少有一段是升序的。根据这个性质,我们进行分类讨论:Ⅰ. 如果nums[left] < nums[mid]且target值介于两者之间,那么需要在nums[left→mid - 1]中查找,否则在nums[mid + 1→right]查找。Ⅱ. 如果nums[mid] < nums[right]且target值介于两者之间,那么需要在nums[mid + 1→right]中查找,否则在nums[left→mid - 1]查找。
时间复杂度为O(log(n))。
代码:
#include <bits/stdc++.h>
using namespace std;
// binary search
class Solution {
public:
int search(vector<int>& nums, int target) {
int n = nums.size();
// Exceptional Case:
if(n == 0){
return -1;
}
int left = 0, right = n - 1;
while(left <= right){
int mid = (left + right) >> 1;
// check left, mid, right
if(nums[left] == target){
return left;
}
if(nums[mid] == target){
return mid;
}
if(nums[right] == target){
return right;
}
if(nums[left] < nums[mid]){
if(nums[left] < target && target < nums[mid]){
right = mid - 1;
}
else{
left = mid + 1;
}
}
else{
if(nums[mid] < target && target < nums[right]){
left = mid + 1;
}
else{
right = mid - 1;
}
}
}
return -1;
}
};