一、題目描述
二、解題思路
要求在的時間複雜度內確定序列裏是否存在這個數字,只能採用二分法
從旋轉的方式可以看出,是把較大的那一半放到前面來了,從而導致原序列區間有序,我們可以確定這個區間的分割點,然後在兩個區間內二分查找。
這種方法一定可以把原序列分成有序的一半和不一定有序的另一半。
但是這樣有個問題,二分查找需要保證原序列遞增有序,那我們怎麼判斷傳入的區間序列是否爲區間有序?答案是比較區間首尾元素大小關係,如果首大尾小,就不是有序序列,這個關係也可以用在算法的開頭,以排除原序列本身就有序的情況。
特殊情況的排除:如果序列爲空,直接返回-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);
}
};
三、運行結果
非遞歸
遞歸