題目
假設按照升序排序的數組在預先未知的某個點上進行了旋轉。( 例如,數組 [0,0,1,2,2,5,6] 可能變為 [2,5,6,0,0,1,2] )。編寫一個函數來判斷給定的目标值是否存在于數組中。若存在傳回 true,否則傳回 false。
示例1 :
輸入: nums = [2,5,6,0,0,1,2], target = 0
輸出: true
示例 2:
輸入: nums = [2,5,6,0,0,1,2], target = 3
輸出: false
注意點
參考:搜尋旋轉排序數組(二分法實作)
1、有序數組經過旋轉後會變為部分有序的數組;
2、我們使用二分法後會出現三種情況如下:
- 情況一:無法判斷左右區間哪個是有序區間,這種情況我們隻能排除一個節點的元素,無法進行區間選擇;(如101111這種情況,則當nums[left] == nums[mid] == nums[right時])
- 情況二:左區間為有序區間,則判斷目标節點是否在有序區間中(左區間),在,則選取左區間;否則,選取右區間;
- 情況二:右區間為有序區間,則判斷目标節點是否在有序區間中(右區間),在,則選取右區間;否則,選取左區間。
實作
public boolean search(int[] nums, int target) {
if (nums == null || nums.length == 0) return false;
int left = 0; //左指針
int right = nums.length - 1; //右指針
while (left <= right){
int mid = left + (right - left) / 2; //中間指針
//如果中間值為目标值,直接傳回
if (nums[mid] == target) return true;
//無法判斷左邊[left,mid)是否為有序區間
if (nums[left] == nums[mid]){
//隻排除一個元素
left ++;
//左邊[left,mid)為有序區間
}else if (nums[left] < nums[mid]){
//目标值在左順序區間中
if (target >= nums[left] && target < nums[mid]){
//取左區間
right = mid - 1;
}else {
//否則,取右區間
left = mid + 1;
}
//左邊[left,mid)為無序區間(則右區間為有序區間)
}else {
//目标值在右順序區間中
if(target > nums[mid] && target <= nums[right]){
//取右區間
left = mid + 1;
}else {
//否則,取左區間
right = mid - 1;
}
}
}
return false;
}