# 【LeetCode & 剑指offer刷题】查找与排序题6：33. Search in Rotated Sorted Array(系列)

【LeetCode & 剑指offer 刷题笔记】目录（持续更新中...）

33. Search in Rotated Sorted Array

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).
Example 1:
Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4
Example 2:
Input: nums = [4,5,6,7,0,1,2], target = 3
Output: -1

/* 掌握

O(logn)
*/
class Solution
{
public:
int search(vector<int>& a, int target)
{
if (a.empty()) return -1;

int left = 0, right = a.size() - 1;
while (left <= right)
{
int mid = (left + right) / 2;

if(a[mid] == target)
return mid;
else if (a[mid] < a[right]) //若中间数小于最右边的数，则右半段（mid~right）是有序的
{
if (target > a[mid] && target <= a[right]) //在有序的半段里用首尾两个数来判断目标值是否在这一区域内
left = mid + 1;//说明在mid~right内，更新left位置
else
right = mid - 1;
}
else                        //若中间数大于最右边的数，则左半段(left~mid)是有序的
{
if (target >= a[left] && target < a[mid])//由于判断下来不可能有 target = a[mid]，故这里没有取等号
right = mid - 1;//说明在left~mid内，更新right位置
else
left = mid + 1;
}
}
return -1;
}
};

//此方法技巧性较高，了解即可
//方法：二分查找（因为有O(logn)的限制）
class Solution
{
public:
int search(vector<int>& a, int target)
{
if(a.empty()) return -1; //特殊情况：空数组

//使用二分查找找到最小值的索引（旋转的地方）
//旋转之后左半边数组比右半边数组大，通过二分查找，找到分界点（最小值）即可，最小值在左半数组最末尾，右半数组起始位置
int n = a.size();
int left=0,right = n-1;
int indexmin = 0; //初始化最小值的位置
while(a[left] > a[right]) //特殊情况：输入有序数组，可以看成rotate 0，则直接退出循环，indexmin用初始值0
{
int mid = (left+right)/2;
if(a[mid]>a[right]) left = mid;//a[mid]>a[right]说明mid在左半边数组，将left指针移至mid
else right = mid; //a[mid]<a[right]说明mid在右半边数组，将right指针移至mid
if(right-left == 1)
{
indexmin = right;break;//跳出循环
}
}//循环结束后left指向左半数组末尾，right指向右半数组开头
//找序列中的极小值（联系find peak element这题）
left = 0;right = n-1;
//使用常规的二分查找(对于增序序列而言)，并考虑旋转
while(left <= right)
{
int mid = (left+right)/2;
int realmid = (mid+indexmin)%n; //indexmin为数组中最小数的位置（本来为0位置，现在变为rot位置），相当于附加偏移以找到真正的mid位置
if(a[realmid] < target) left = mid+1;
else if(a[realmid] > target) right = mid-1;
else return realmid;
}
return -1;//未找到
}
};

81. Search in Rotated Sorted Array II
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e., [0,0,1,2,2,5,6] might become [2,5,6,0,0,1,2]).
You are given a target value to search. If found in the array return true, otherwise return false.
Example 1:
Input: nums = [2,5,6,0,0,1,2], target = 0
Output: true
Example 2:
Input: nums = [2,5,6,0,0,1,2], target = 3
Output: false
• This is a follow up problem to Search in Rotated Sorted Array, where nums may contain duplicates.
• Would this affect the run-time complexity? How and why?

/*

O(logn)
*/
class Solution
{
public:
bool search(vector<int>& a, int target)
{
if (a.empty()) return false;

int left = 0, right = a.size() - 1;
while (left <= right)
{
int mid = (left + right) / 2;

if(a[mid] == target)
return true;
else if (a[mid] < a[right]) //若中间数小于最右边的数，则右半段（mid~right）是有序的
{
if (target > a[mid] && target <= a[right]) //在有序的半段里用首尾两个数来判断目标值是否在这一区域内
left = mid + 1;//说明在mid~right内，更新left位置
else
right = mid - 1;
}
else if (a[mid] > a[right]) //若中间数大于最右边的数，则左半段(left~mid)是有序的
{
if (target >= a[left] && target < a[mid])//由于判断下来不可能有 target = a[mid]，故这里没有取等号
right = mid - 1;//说明在left~mid内，更新right位置
else
left = mid + 1;
}
else             //若中间数等于最右边数，移动right指针
right--;
}
return false;
}
};

posted @ 2019-01-05 20:10  wikiwen  阅读(296)  评论(0编辑  收藏