题目:
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.
Your algorithm’s runtime complexity must be in the order of O(log n).
思路:
首先,利用二分法,找到旋转数组分界点。然后,判断target在左半边还是右半边。最后,利用二分法搜索target。整个算法的时间复杂度为O(log n)。(数组无重复元素让这个题目简单不少)
代码实现:
class Solution {
public:
int binary_search(const vector<int>& nums, int begin, int end, int target){
int left = begin;
int right = end;
int mid = left + (right - left) / 2;
while (left <= right){ // 等号很重要,不要落下
if (nums[mid] == target){
return mid;
}else if (nums[mid] > target){
right = mid - 1;
}else{
left = mid + 1;
}
mid = left + (right - left) / 2;
}
return -1;
}
int search(vector<int>& nums, int target) {
if (nums.size() <= 0){
return -1;
}
int left = 0;
int right = nums.size()-1;
int mid = left + (right - left) / 2;
// 寻找分界点
while (left <= right){ // 等号很重要,不要落下
if (nums[mid] >= nums[0]){ // 这里等号也很重要,因为mid有可能等于0
left = mid + 1;
}else{
right = mid - 1;
}
mid = left + (right - left) / 2;
}
// 判断target在左半边还是右半边
if (left >= nums.size()){
return binary_search(nums, 0, nums.size()-1, target);
}else{
if (target >= nums[0]){
return binary_search(nums, 0, left-1, target);
}else{
return binary_search(nums, left, nums.size()-1, target);
}
}
return -1;
}
};
discuss:
先假象没有旋转,然后求出mid,再将mid旋转一下,再与target比较。扭着身子做二分查找。
class Solution {
public:
int search(vector<int>& nums, int target) {
int lo = 0, hi = n-1; // 首、尾元素
while (lo < hi){
int mid = (lo + hi) / 2;
if (A[mid] > A[hi]){
lo = mid + 1;
}else{
hi = mid;
}
}
// 此时lo == hi是最小值,也是整个数组旋转的地方
int rot = lo; // 旋转次数
lo = 0; hi = n - 1; // 默认是不旋转的
while (lo <= hi){
int mid = (lo + hi) / 2;
int realmid = (mid + rot) % n; // mid是不旋转的情况,将mid旋转之后变成realmid
if (A[realmid] == target){
return realmid;
}
if (A[realmid] < target){
lo = mid + 1;
}else {
hi = mid - 1;
}
}
return -1;
}
};