題目描述
把一個數組最開始的若干個元素搬到數組的末尾,我們稱之爲數組的旋轉。
輸入一個非遞減排序的數組的一個旋轉,輸出旋轉數組的最小元素。
例如數組{3,4,5,1,2}
爲{1,2,3,4,5}
的一個旋轉,該數組的最小值爲1。
NOTE:給出的所有元素都大於0,若數組大小爲0,請返回0。
這道題讓我們在一個特殊的數組中找最小值,這個特殊的數組是有非遞減的數組變形而來,比如原數組{1,2,3,4,5}
,變形後的數組{3,4,5,1,2}
,就是把數組的後半段移動到數組的前面。
如果是一個遞增的數組,稍微熟悉算法的道友都知道二分查找
。那麼這道題給的變形數組能進行二分查找
麼?下面演示一下數組nums{6、7、8、9、2、3、4、5}
中的最小值查找過程:
初始化:left = 0, right = 7,mid = 0
第1步:left = 0, right = 7,mid = (left + right) / 2 = 3
顯然nums[mid] > nums[right]
那麼最小值必定出現在[mid + 1, right]中!!!left = mid + 1
因爲兩個半段仍然保持段內有序,如果min出現在左半段,左邊段必然不是遞增
第2步:left = 4, right = 7,mid = (left + right) / 2 = 5
顯然nums[mid] ≯ nums[right]
那麼最小值必定出現在[left, mid]中!!!right = mid = 5
因爲兩個半段仍然保持段內有序,如果min出現在右半段,右邊段必然不是遞增
第3步:left = 4, right = 5,mid = (left + right) / 2 = 4
顯然nums[mid] ≯ nums[right]
那麼最小值必定出現在[left, mid]中!!!right = 4
因爲兩個半段仍然保持段內有序,如果min出現在右半段,右邊段必然不是遞增
left = right = 4,結束查找,min = nums[4] = 2.
這不就是二分查找的變形了,只是判斷的條件不同。
注意分成的兩段,各段段內仍然保持非遞減有序是這題的關鍵!
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
int left = 0, right = rotateArray.size() - 1, mid;
//變形二分查找
while (left < right) {
mid = (left + right) / 2;
//rotateArray[mid]大於rotateArray[right],則最小值必定出現在右半段
if (rotateArray[right] < rotateArray[mid]) {
left = mid + 1;
} else {
//否則我們取左半段
right = mid;
}
}
return rotateArray[left];
}
};
題1、LeetCode 子集(回溯法)
題2、LeetCode 組合(回溯法)
題3、LeetCode 最小覆蓋子串(雙指針窗口滑動)