劍指offer 旋轉數組的最小數字(變形二分搜索)

題目描述
把一個數組最開始的若干個元素搬到數組的末尾,我們稱之爲數組的旋轉。
輸入一個非遞減排序的數組的一個旋轉,輸出旋轉數組的最小元素。
例如數組{3,4,5,1,2}{1,2,3,4,5}的一個旋轉,該數組的最小值爲1。
NOTE:給出的所有元素都大於0,若數組大小爲0,請返回0。

\color{blue}解題思路:
這道題讓我們在一個特殊的數組中找最小值,這個特殊的數組是有非遞減的數組變形而來,比如原數組{1,2,3,4,5},變形後的數組{3,4,5,1,2},就是把數組的後半段移動到數組的前面。

使\color{red}注意:即使分成兩段,仍然保持段內非遞減有序,

3,4,51,2.\color{red}比如左半段{3,4,5}、右半段{1,2}.

如果是一個遞增的數組,稍微熟悉算法的道友都知道二分查找。那麼這道題給的變形數組能進行二分查找麼?下面演示一下數組nums{6、7、8、9、2、3、4、5}中的最小值查找過程:

初始化:left = 0, right = 7,mid = 01步: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.

這不就是二分查找的變形了,只是判斷的條件不同。
注意分成的兩段,各段段內仍然保持非遞減有序是這題的關鍵!

\color{blue}代碼實現:

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];
    }
};

在這裏插入圖片描述
\color{blue}題目推薦:
題1、LeetCode 子集(回溯法)
題2、LeetCode 組合(回溯法)
題3、LeetCode 最小覆蓋子串(雙指針窗口滑動)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章