原題鏈接:https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/
我在github上的leetcode倉庫:https://github.com/cooljacket/leetcodes
題意
定義翻轉有序數組:一個升序數組,從中間某個元素切開,把左右兩部分互換位置。
比如[1, 2, 3, 4, 5, 6, 7]從3處切開成爲[1, 2, 3]和[4, 5, 6, 7],兩部分互換位置,變成[4, 5, 6, 7, 1, 2, 3]。
給定這樣一個數組,要求找出其中最小的元素出來!
這一題的要求比較簡單,輸入沒有重複的元素;
有重複元素的版本見:http://blog.csdn.net/Jacketinsysu/article/details/52299291
思路
這樣的數組的特徵是很明顯的,就是如下圖所示的趨勢:
細節1
用二分查找的思路很直接,需要確定的細節就是:如何移動左右端?
用low,high和mid分別表示左端、右端和區間中點。
如果mid是落在A區的話,很明顯有nums[mid] > nums[high],反之亦然。
若mid是落在B區的,則有nums[mid] < nums[high],反之亦然。
當mid落在A區時,很明顯可以low = mid + 1;
當mid落在B區時,只能high = mid。爲什麼不能mid - 1呢?因爲如此時mid剛好指向的是最小值,-1就過頭了!
細節2
其實還有一個細節,就是mid的計算,它有兩個方法:
1)mid = (low + high) >> 1;
2)mid = (low + high + 1) >> 1;
這兩種計算方法具體會產生什麼不同的效果呢?
其實有經驗的人就會知道,二分查找過程中,最最關鍵的地方,就是收斂到最後只剩下兩個元素的時候,怎麼取捨,決定了mid要偏左還是偏右!(這裏說得有點懸,改天再寫一篇二分查找的專題)
這裏舉個簡單的例子就好了,比如最後的區間是這樣的:[1, 0],然後如果用的是第二種計算mid的方法,就會死循環了,因爲mid一直會等於high!而high在比較過後又會變成mid,一直不變!
代碼
沒有重複的元素,代碼很簡單:
class Solution {
public:
int findMin(vector<int>& nums) {
int low = 0, high = nums.size() - 1, mid;
while (low < high) {
mid = (low + high) >> 1;
if (nums[mid] > nums[high])
low = mid + 1;
else
high = mid;
}
return nums[low];
}
};