假設按照升序排序的數(shù)組在預先未知的某個點上進行了旋轉捐下。
( 例如弧哎,數(shù)組 [0,1,2,4,5,6,7] 可能變?yōu)?[4,5,6,7,0,1,2] )。
搜索一個給定的目標值淳蔼,如果數(shù)組中存在這個目標值侧蘸,則返回它的索引,否則返回 -1 肖方。
你可以假設數(shù)組中不存在重復的元素闺魏。
你的算法時間復雜度必須是 O(log n) 級別。
示例 1:
輸入: nums = [4,5,6,7,0,1,2], target = 0
輸出: 4
示例 2:
輸入: nums = [4,5,6,7,0,1,2], target = 3
輸出: -1
解答:
解題思路:
這道題讓在旋轉數(shù)組中搜索一個給定值俯画,若存在返回坐標析桥,若不存在返回-1。我們還是考慮二分搜索法艰垂,但是這道題的難點在于我們不知道原數(shù)組在哪旋轉了泡仗,我們還是用題目中給的例子來分析,對于數(shù)組[0 1 2 4 5 6 7] 共有下列七種旋轉方法:
0 1 2 4 5 6 7
7 0 1 2 4 5 6
6 7 0 1 2 4 5
5 6 7 0 1 2 4
4 5 6 7 0 1 2
2 4 5 6 7 0 1
1 2 4 5 6 7 0
二分搜索法的關鍵在于獲得了中間數(shù)后猜憎,判斷下面要搜索左半段還是右半段娩怎,我們觀察上面紅色加粗的數(shù)字都是升序的(前4行),由此我們可以觀察出規(guī)律胰柑,如果中間的數(shù)小于最右邊的數(shù)截亦,則右半段是有序的爬泥,若中間數(shù)大于最右邊數(shù),則左半段是有序的崩瓤,我們只要在有序的半段里用首尾兩個數(shù)組來判斷目標值是否在這一區(qū)域內(nèi)袍啡,這樣就可以確定保留哪半邊了。
class Solution {
public:
int search(vector<int>& nums, int target) {
if(nums.size()<=0) // 數(shù)組為空
return -1;
int t1=0,t2=nums.size()-1; // 雙動態(tài)指針
while(t1<=t2){
int mid=(t1+t2)/2; // 中位數(shù)
if(nums[mid]==target)
return mid;
else if(nums[mid]<nums[t2]){
if(nums[mid]<target && nums[t2]>=target)
t1=mid+1; // 之所以加一是因為中位數(shù)前面已經(jīng)比較過了
else
t2=mid-1;
} // 若中位數(shù)小于最右的數(shù)却桶,說明右半部分是有序的境输,先在右邊查找
else{
if(nums[t1]<=target && nums[mid]>target)
t2=mid-1;
else
t1=mid+1;
} // 否則,左半部分有序颖系,先在左邊查找
}
return -1; // 找不到嗅剖,返回-1
}
};