假設按照升序排序的數組在預先未知的某個點上進行了旋轉。例如,數組 [0,1,2,4,5,6,7] 可能變爲 [4,5,6,7,0,1,2] 。c++
請找出其中最小的元素。數組
示例 1:網絡
輸入:nums = [3,4,5,1,2]
輸出:1
示例 2:ui
輸入:nums = [4,5,6,7,0,1,2]
輸出:0
示例 3:指針
輸入:nums = [1]
輸出:1code
來源:力扣(LeetCode)
連接:https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array
著做權歸領釦網絡全部。商業轉載請聯繫官方受權,非商業轉載請註明出處。排序
本思路是歸納了題目和修改後的題目,暴力破解都是這個方法。ip
原數組是非遞減的,旋轉後,有兩種狀況,數組還是非遞減的,例如將所有元素放到數組的末尾,它至關於仍是原數組,或者有重複項,例如 {2,2,2,2},旋轉後還是非遞減的,那麼咱們返回第一個元素便可。另外一種狀況就會出現前一個元素大於後一個元素,那麼後一個元素必定是最小的,也就是咱們要的解。leetcode
int findMin(vector<int>& nums) { if(!nums.size()) return -1; for(int i = 0; i < nums.size() - 1; i++) { if(nums[i] > nums[i + 1]) return nums[i + 1]; } return nums[0]; }
此思路是假設沒有重複的數。get
咱們知道,當數組是已經排序好的,咱們能夠用二分法來查找,其實本題也能夠利用二分法來作。
咱們找一箇中間值,若是這個中間值小於此時的left,那麼就意味着咱們要找的數就在left 到 mid 中間,若是中間值大於left,那麼咱們要找的值就在mid到right中間,直到縮減到兩個數的時候,此時左指針指向的數必定大於右指針指向的數,mid此時就會在左指針的位置上,咱們返回右指針便可
class Solution { public: int findMin(vector<int>& nums) { int left = 0; int right = nums.size() - 1; int mid = (left + right) / 2; if (nums[left] < nums[right]) { return nums[left]; } while (left != mid) { if (nums[mid] > nums[left]) { left = mid; } else if (nums[mid] < nums[right]) { right = mid; } mid = (left + right) / 2; } return nums[right]; } };
把一個數組最開始的若干個元素搬到數組的末尾,咱們稱之爲數組的旋轉。
輸入一個升序的數組的一個旋轉,輸出旋轉數組的最小元素。
例如數組{3,4,5,1,2}爲{1,2,3,4,5}的一個旋轉,該數組的最小值爲1。
數組可能包含重複項。
注意:數組內所含元素非負,若數組大小爲0,請返回-1。
輸入:nums=[2,2,2,0,1] 輸出:0
題目中容許出現重複的數字,這就意味着在原來的理解上咱們要多一層可能,那就是中間的值等於左側值或者右側的值,舉一個例子[2,2,2,1,1,2],此時mid指向第三個2,最小值在mid的右側;[2,2,2,1,1,2,2,2,2,2,2],此時最小值在mid左側。這樣咱們就須要來判斷此時咱們是要在左側尋找仍是在右側尋找了。但無論怎麼樣,若是相同,咱們能夠省略掉相同的數的那個指針。
因此分三種狀況,當中間的比最右端的小,此時咱們讓右指針移動過來,當中間的比右邊打,咱們讓左指針移到中間指針的後方,若是相等,就讓右指針移動。
class Solution { public: int findMin(vector<int>& nums) { int low = 0; int high = nums.size() - 1; while (low < high) { int pivot = low + (high - low) / 2; if (nums[pivot] < nums[high]) { high = pivot; } else if (nums[pivot] > nums[high]) { low = pivot + 1; } else { high -= 1; } } return nums[low]; } };
詳細內容能夠看這裏,講的真的很好。