力扣 33. 搜尋旋轉排序陣列
題目
33. 搜尋旋轉排序陣列
整數陣列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
提示:
1 <= nums.length <= 5000
-10^4 <= nums[i] <= 10^4
nums
中的每個值都獨一無二- 題目資料保證
nums
在預先未知的某個下標上進行了旋轉 -10^4 <= target <= 10^4
進階:你可以設計一個時間複雜度為O(log n)
的解決方案嗎?
官方
方法一:二分查詢
思路和演算法
對於有序陣列,可以使用二分查詢的方法查詢元素。
但是這道題中,陣列本身不是有序的,進行旋轉後只保證了陣列的區域性是有序的,這還能進行二分查詢嗎?答案是可以的。
可以發現的是,我們將陣列從中間分開成左右兩部分的時候,一定有一部分的陣列是有序的。拿示例來看,我們從 6 這個位置分開以後陣列變成了 [4, 5, 6] 和 [7, 0, 1, 2] 兩個部分,其中左邊 [4, 5, 6] 這個部分的陣列是有序的,其他也是如此。
這啟示我們可以在常規二分查詢的時候檢視當前 mid 為分割位置分割出來的兩個部分 [l, mid] 和 [mid + 1, r] 哪個部分是有序的,並根據有序的那個部分確定我們該如何改變二分查詢的上下界,因為我們能夠根據有序的那部分判斷出 target 在不在這個部分:
如果 [l, mid - 1] 是有序陣列,且 target 的大小滿足 [nums[l],nums[mid]),則我們應該將搜尋範圍縮小至 [l, mid - 1],否則在 [mid + 1, r] 中尋找。
如果 [mid, r] 是有序陣列,且 target 的大小滿足 (nums[mid+1],nums[r]],則我們應該將搜尋範圍縮小至 [mid + 1, r],否則在 [l, mid - 1] 中尋找。
作者:LeetCode-Solution
連結:https://leetcode-cn.com/problems/search-in-rotated-sorted-array/solution/sou-suo-xuan-zhuan-pai-xu-shu-zu-by-leetcode-solut/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。
class Solution { public: int search(vector<int>& nums, int target) { int r=nums.size()-1; int l=0; if(r==0) return nums[0]==target?0:-1; while(l<=r) { int mid=(l+r)/2; if(nums[mid]==target) return mid; if(nums[0]<=nums[mid])//左邊有序 { if(nums[l]<=target&&nums[mid]>target)//t在區間[nums[l],num[mid])中,往左邊 r=mid-1; else l=mid+1; } else //.右邊有序 { if(nums[mid]<target&&nums[r]>=target)//t在區間[nums[mid],num[r])中,往右邊 l=mid+1; else r=mid-1; } } return -1; } };
Std
find()
vector< int >::iterator iter=std::find(nums.begin(),nums.end(),target); //返回的是一個迭代器指標
distance()
std::distance(nums.begin(), iter);
class Solution { public: int search(vector<int>& nums, int target) { vector< int >::iterator iter=std::find(nums.begin(),nums.end(),target); //返回的是一個迭代器指標 if (iter==nums.end()) return -1; else //注意迭代器指標輸出元素的方式和distance用法 return std::distance(nums.begin(), iter); } };