153. 尋找旋轉排序數組中的最小值【力扣】

題意理解

對一個數組旋轉一部分元素,求數組中的最小值。

問題分析

找特徵,如果旋轉元素個數爲0,那麼最小數就是數組的第一個數字;如果個數不爲0,那麼最小元素藏在中間。旋沒旋轉可以通過判斷首元素和尾元素大小判斷。對於最小元素藏在中間的情況,使用二分法,最小元素左邊的元素都比首元素大,右邊的元素都比首元素小。判斷mid是不是最小,可以通過特徵鄰接元素比大小來判斷。

補充20200509:以上思路如果出現首尾中間三值相等無法正確處理。轉換思路如下:

經過旋轉後的數組分爲兩段,左邊一段遞增,右邊一段遞增,左邊一段比右邊一段都大。最小值的位置在右邊一段的最前面。

low的變化範圍包括左邊一段+最小值;high的變化範圍包括右邊一段。

取中以後,如何移動low,high位置呢?將mid值和high值比較,如果比mid值大,說明在左邊一段,將low設置爲mid後一位,不是mid,因爲low的範圍可以包含最小值;如果比mid值小,說明在右邊一段,將high設置爲mid位,不是mid-1,因爲high的範圍不能超過右邊一段。這樣直到low==high,這時候的落點一定是最小值。

其他

同類型題目:https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof/

鏈接

 

class Solution {
public:
    int findMin(vector<int>& nums) {
        int len=nums.size();
        if(len==0) return -1;
        if(len==1) return nums[0];
        
        
        if(nums[0]<nums[len-1]) {    //沒有旋轉元素的情況
            return nums[0];
        }
        else {
            int low=0, high=len-1;    
            while(low<high) {    //二分查找
                int mid=(low+high)/2;
                if(nums[mid]>nums[mid+1]) return nums[mid+1]; //最小值判斷
                if(nums[mid-1]>nums[mid]) return nums[mid];    //最小值判斷
                if(nums[mid]>nums[0]) {    //縮小範圍
                    low=mid+1;
                }
                else {    //縮小範圍
                    high=mid-1;
                }
            }
        }
        return -1;
    }
};

0509:

    int minArray(vector<int>& numbers) {
        int low = 0;    //小端範圍在最小值及最小值左邊
        int high = numbers.size() - 1;  //大端範圍僅在最小值及最小值右邊
        while (low < high) {
            int mid = low + (high - low) / 2;
            if (numbers[mid] < numbers[high]) {
                high = mid;
            }
            else if (numbers[mid] > numbers[high]){
                low = mid + 1;
            }
            else {
                high --;    //關鍵代碼
            }
        }
        return numbers[low];
    }

 

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