代碼題(20)— 旋轉數組找值
1、154. 尋找旋轉排序數組中的最小值 II
假設按照升序排序的數組在預先未知的某個點上進行了旋轉。
( 例如,數組 [0,1,2,4,5,6,7]
可能變為 [4,5,6,7,0,1,2]
)。
請找出其中最小的元素。
註意數組中可能存在重復的元素。
class Solution { public: int findMin(vector<int>& nums) { if(nums.empty()) return -1; int low = 0; int high = nums.size()-1;while(low<=high) { int mid = (low+high)/2; if(nums[mid]>nums[high]) low = mid+1; else if(nums[mid]<nums[high]) high = mid; else high--; } return nums[low]; } };
2、33、搜索旋轉排序數組
假設按照升序排序的數組在預先未知的某個點上進行了旋轉。
( 例如,數組 [0,1,2,4,5,6,7]
可能變為 [4,5,6,7,0,1,2]
)。
搜索一個給定的目標值,如果數組中存在這個目標值,則返回它的索引,否則返回 -1
。
你可以假設數組中不存在重復的元素。
你的算法時間復雜度必須是 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
思路:二分搜索法的關鍵在於獲得了中間數後,判斷下面要搜索左半段還是右半段,我們觀察上面紅色的數字都是升序的,由此我們可以觀察出規律,如果中間的數小於最右邊的數,則右半段是有序的,若中間數大於最右邊數,則左半段是有序的,我們只要在有序的半段裏用首尾兩個數組來判斷目標值是否在這一區域內,這樣就可以確定保留哪半邊了,
class Solution { public: int search(vector<int>& nums, int target) { if(nums.size() == 0) return -1; int low = 0, high = nums.size()-1; while(low<=high) { int mid=(low+high)*0.5; if(nums[mid] == target) return mid; else if(nums[mid] > nums[high])//中間值大於最右邊的數,則左半段是有序的 { if(nums[low] <= target && nums[mid] > target) high = mid-1; else low = mid+1; } else { if(nums[mid] < target && nums[high] >= target) //中間值小於最右邊的數,則右半段是有序的 low = mid+1; else high = mid-1; } } return -1; } };
3、81. 搜索旋轉排序數組 II
假設按照升序排序的數組在預先未知的某個點上進行了旋轉。
( 例如,數組 [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
進階:
- 這是 搜索旋轉排序數組 的延伸題目,本題中的
nums
可能包含重復元素。 - 這會影響到程序的時間復雜度嗎?會有怎樣的影響,為什麽?
現在數組中允許出現重復數字,這個也會影響我們選擇哪半邊繼續搜索,由於之前那道題不存在相同值,我們在比較中間值和最右值時就完全符合之前所說的規律:如果中間的數小於最右邊的數,則右半段是有序的,若中間數大於最右邊數,則左半段是有序的。而如果可以有重復值,就會出現來面兩種情況,[3 1 1] 和 [1 1 3 1],對於這兩種情況中間值等於最右值時,目標值3既可以在左邊又可以在右邊,那怎麽辦麽,對於這種情況其實處理非常簡單,只要把最右值向左一位即可繼續循環,如果還相同則繼續移,直到移到不同值為止,然後其他部分還采用 Search in Rotated Sorted Array 在旋轉有序數組中搜索 中的方法。
class Solution { public: bool search(vector<int>& nums, int target) { int res = false; if(nums.empty()) return res; int low = 0; int high = nums.size()-1; while(low <= high) { int mid = (low+high)/2; if(nums[mid] == target) return true; else if(nums[mid]>nums[high]) { if(nums[mid] >target && nums[low] <= target) high = mid-1; else low = mid+1; } else if(nums[mid] < nums[high]) { if(nums[mid] < target && nums[high] >= target) low = mid+1; else high = mid-1 ; } else high--; } return res; } };
代碼題(20)— 旋轉數組找值