LeetCode154. 尋找旋轉排序陣列中的最小值 II
阿新 • • 發佈:2020-07-31
經過旋轉後的陣列,滿足這樣一個性質,最小值右邊的元素,都大於等於最小值(因為這題有重複元素,所以有可能等於),最小值左邊的元素,都大於等於最小值。
所以每一次二分,我們可以與當前區間的最左邊或最右邊進行比較,確定最小值的位置。
這裡我們每次將區間中點的值nums[mid]與區間右端點nums[right]進行比較。
-
如果nums[mid] < nums[right],這說明區間右半部分是升序的,那麼最小值肯定不在這部分,最小值最大隻能是nums[mid],所以讓right = mid;
-
如果nums[mid] < nums[right],這說明區間右半部分不是升序的,說明陣列的旋轉位置就在右半部分,最小值肯定在mid + 1 ~ right這部分,所以讓left = mid + 1;
-
如果nums[mid] == nums[right],這有幾種情況,一種陣列全都是相同元素,一種是在mid和right之間先上升後下降,後者mid和right之間先下降後上升,不管怎樣,我們還需要在這個區間內繼續尋找元素,
只不過現在不能直接折半了,而只能讓right -= 1(或--right),也就是刪去一個重複元素,繼續判斷nums[mid]和nums[right](這裡的right是剛才那個right的前一個位置)的大小關係。
因為第三種情況最壞情況下每次只能去掉一個元素,所以這題最壞情況下的時間複雜度是O(n)。
程式碼如下:
class Solution { public: int findMin(vector<int>& nums) { int left = 0, right = nums.size() - 1; while(left < right) { int mid = (left + right) >> 1; if(nums[mid] < nums[right]) { right = mid; } else if(nums[mid] > nums[right]) { left = mid + 1; } else { --right; } } return nums[left]; //這裡nums[left]和nums[right]都可以 } };