原創博文,轉載請註明出處!ios
# 本文是牛客網《劍指offer》刷題筆記數組
1.題目
旋轉數組的最小數字:輸入一個非遞減排序的數組的一個旋轉,輸出旋轉數組的最小元素。 例如數組{3,4,5,1,2}爲{1,2,3,4,5}的一個旋轉,該數組的最小值爲1。測試
注意:給出的全部元素都大於0,若數組大小爲0,請返回0。spa
2.思路
- 空數組查找最小元素:
輸出0指針
- 非空數組查找最小元素:
# 若是輸入旋轉0個元素的旋轉數組,則第一個元素即最小元素 code
# 若是輸入旋轉n個元素的旋轉數組,則按二分查找和順序查找的思路查找最小元素blog
二分查找過程:排序
旋轉數組特性:旋轉數組將原有序數組分紅遞增子數組1和遞增子數組2,遞增子數組1的元素>=遞增子數組2,最小元素是兩個子數組的分界線。設置輔助變量:指針left指向旋轉數組的第一個元素;指針mid指向旋轉數組中間位置的元素;指針right指向旋轉數組最後一個元素。get
若是mid指向的元素>=left指向的元素,則mid位於遞增子數組1,數組中最小元素位與中間元素的後面,將left指向mid後,縮小一半的尋找範圍it
若是mid指向的元素<=right指向的元素,則mid位於遞增子數組2,數組中最小元素位與中間元素的前面,將right指向mid後,縮小一半的尋找範圍
若是mid指向的元素==left指向的元素==right指向的元素,則沒法肯定mid位於哪一個遞增子數組,沒法折半查找,只能順序查找
二分查找結束標誌:
left指針始終指向遞增子數組1,right指針始終指向遞增子數組2,最終left指針指向遞增子數組1的最後一個元素,right指針指向遞增子數組2的第一個元素。當left+1=right時結束循環,right位置的元素即爲最小元素。7
3.code
#include <iostream> #include <vector> using namespace std; class Solution { public: int minNumberInRotateArray(vector<int> rotateArray) { // 空數組 int size = rotateArray.size(); //數組長度 if(size == 0) { return 0; } // 非空數組 int left = 0; //左指針 int right = size - 1; //右指針 int mid = 0; //中間指針(未旋轉時直接輸出rotateArray[0]) while(rotateArray[left] >= rotateArray[right]) { // 循環結束標誌(左右指針相鄰) if(left+1 == right) { mid = right; break; } // 計算中間指針位置 mid = left + (right - left) / 2; //特殊狀況:若是沒法肯定中間元素是屬於前面仍是後面的遞增子數組,只能順序查找 if(rotateArray[left] == rotateArray[right] && rotateArray[mid] == rotateArray[left]){ return MinInOrder(rotateArray, left, right); } //中間元素位於前面的遞增子數組,此時最小元素位於中間元素的後面 if(rotateArray[mid] >= rotateArray[left]){ left = mid; } //中間元素位於後面的遞增子數組,此時最小元素位於中間元素的前面 else{ right = mid; } } return rotateArray[mid]; } private: //順序尋找最小值 int MinInOrder(vector<int> &num, int left, int right){ int result = num[left]; for(int i = left + 1; i <= right; i++){ if(num[i] < result){ result = num[i]; } } return result; } }; int main() { Solution solution; vector<int> rotateArray = {4,5,1,2,3,4}; cout<<solution.minNumberInRotateArray(rotateArray)<<endl; return 0; }
4.複雜度
時間複雜度O(logn)
5.測試用例
- 空指針
- 一個元素的數組
- 未旋轉的數組
- 旋轉的數組(無重複數字和有重複數字)