LeetCode 153, 154. Find Minimum in Rotated Sorted Array I & II
153. Find Minimum in Rotated Sorted Array
二分題目,由於rotated存在,a[mid]<key不能判斷在哪一邊搜尋。
可以根據a[low]與a[high]的關係,來判斷哪一邊有序,哪一邊存在rotate,進而縮小搜尋區間。
開區間寫法:(由於搜尋區間和解區間都是[low, high],直接 [low, high])
class Solution { public: int findMin(vector<int>& nums) { int low=0, high=nums.size()-1; //[low,high] while (low<high){ if (nums[low]<nums[high]) return nums[low]; int mid=(low+high)/2; if (nums[mid]>nums[high]){ //left side in order, min in the right part low = mid+1; }else{ //right side in order, min in the left parthigh = mid; } } return nums[low]; } };
上面的寫法是用 a[mid] 與 a[high] 比較的,這樣是比與 a[low] 比較要好的。如果和 a[low] 比較,需要注意的是 a[low]=a[mid] 可能發生,由於沒有重複元素,這種情況只可能在 low==mid 時發生,即 low=mid=high-1 時。由於上面 a[low]<a[high] 就會return,說明這裡 a[low]>a[high],應該返回 high 的值,因此歸類歸到 a[low]<a[mid] 一類中。
這道題的followup,如果有重複元素,a[low]==a[mid] 即有可能是 low==mid 這一邊界情況,也有可能是重複元素導致的 a[low]==a[mid],需要分別處理,比較繁瑣。
而與 a[high] 比較,a[mid]==a[high] 只可能是重複元素導致的。
class Solution { public: int findMin(vector<int>& nums) { int low=0, high=nums.size()-1; //[low,high] while (low<high){ if (nums[low]<nums[high]) return nums[low]; int mid=(low+high)/2; if (nums[low]<=nums[mid]){ //left side in order, min in the right part low = mid+1; }else{ //right side in order, min in the left part high = mid; } } return nums[low]; } };
154. Find Minimum in Rotated Sorted Array II
有duplicate以後,nums[mid]==nums[high] 的情況就會發生,我們無法判斷最小值是左邊還是右邊。
由於二分實質是維護low,high只是用來縮小區間,我們可以 --high,這樣並不會把最小的元素skip掉。
class Solution { public: int findMin(vector<int>& nums) { int low=0, high=nums.size()-1; //[low,high] while (low<high){ if (nums[low]<nums[high]) return nums[low]; int mid=(low+high)/2; if (nums[mid]>nums[high]){ //left side in order, min in the right part low = mid+1; }else if (nums[mid]<nums[high]){ //right side in order, min in the left part high = mid; }else{ // nums[mid]==nums[high] --high; } } return nums[low]; } };
類似題目:
Search in Rotated Sorted Array
reference: