leetcdoe 33. 搜尋旋轉排序陣列
33. 搜尋旋轉排序陣列
地址:https://leetcode-cn.com/problems/search-in-rotated-sorted-array/
題目描述
整數陣列 nums 按升序排列,陣列中的值 互不相同 。
在傳遞給函式之前,nums 在預先未知的某個下標 k(0 <= k < nums.length)上進行了 旋轉,使陣列變為 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下標 從 0 開始 計數)。例如, [0,1,2,4,5,6,7] 在下標 3 處經旋轉後可能變為[4,5,6,7,0,1,2] 。
給你 旋轉後 的陣列 nums 和一個整數 target ,如果 nums 中存在這個目標值 target ,則返回它的下標,否則返回-1。
示例
示例 1:
輸入:nums = [4,5,6,7,0,1,2], target = 0
輸出:4
示例2:
輸入:nums = [4,5,6,7,0,1,2], target = 3
輸出:-1
示例 3:
輸入:nums = [1], target = 0
輸出:-1
分析
由於是有序陣列找指定數字 所以明顯是用二分查詢來解決
但是由於陣列中存在反轉,所以需要對二分的判定標準進行修改,判定左右是否有序
當target值大於nums[mid}時,普通的有序陣列是去陣列的右側,即[mid+1,right]繼續進行二分,
而反轉有序陣列 先判定右側是否有序(nums[mid]<=nums[right]),當該區間有序且nums[right]>=target時 繼續在該區間進行二分,若區間無序說明 左區間[left,mid-1]必有序,不可能存在target,因此繼續在右側區間二分 ,其餘情況都去左側區間查詢
官方思路
在常規二分查詢的時候檢視當前 mid 為分割位置分割出來的兩個部分 [l, mid] 和 [mid + 1, r] 哪個部分是有序的,並根據有序的那個部分確定我們該如何改變二分查詢的上下界,因為我們能夠根據有序的那部分判斷出 target 在不在這個部分:
如果 [l, mid - 1] 是有序陣列,且 target 的大小滿足 [nums[l],nums[mid])[nums[l],nums[mid]),則我們應該將搜尋範圍縮小至 [l, mid - 1],否則在 [mid + 1, r] 中尋找。
如果 [mid, r] 是有序陣列,且 target 的大小滿足 (nums[mid+1],nums[r]](nums[mid+1],nums[r]],則我們應該將搜尋範圍縮小至 [mid + 1, r],否則在 [l, mid - 1] 中尋找。
程式碼
class Solution {
public:
int search(vector<int>& nums, int target) {
int left=0;
int right = nums.size()-1;
int mid=0;
while(right>=left)
{
mid =(left+right)/2;
if(nums[mid]==target)
{
return mid;
}else if(nums[mid]>target)
{
if(nums[left]<=nums[mid] && nums[left]<=target ||nums[mid]<=nums[right])
right =mid -1;
else
left =mid+1;
}else{
if(nums[mid]<nums[right] && nums[right]>= target || nums[left]<=nums[mid])
{
left =mid+1;
}else
{
right =mid -1;
}
}
}
return -1;
}
};
官方題解
class Solution {
public:
int search(vector<int>& nums, int target) {
int n = (int)nums.size();
if (!n) {
return -1;
}
if (n == 1) {
return nums[0] == target ? 0 : -1;
}
int l = 0, r = n - 1;
while (l <= r) {
int mid = (l + r) / 2;
if (nums[mid] == target) return mid;
if (nums[0] <= nums[mid]) {
if (nums[0] <= target && target < nums[mid]) {
r = mid - 1;
} else {
l = mid + 1;
}
} else {
if (nums[mid] < target && target <= nums[n - 1]) {
l = mid + 1;
} else {
r = mid - 1;
}
}
}
return -1;
}
};