1. 程式人生 > 其它 >IO流之緩衝流

IO流之緩衝流

一個不包含重複元素的升序陣列在經過旋轉之後,可以得到下面視覺化的折線圖:

其中橫軸表示陣列元素的下標,縱軸表示陣列元素的值。圖中標出了最小值的位置,是我們需要查詢的目標。

我們考慮陣列中的最後一個元素 x:在最小值右側的元素(不包括最後一個元素本身),它們的值一定都嚴格小於 x;而在最小值左側的元素,它們的值一定都嚴格大於 x。因此,我們可以根據這一條性質,通過二分查詢的方法找出最小值。

在二分查詢的每一步中,左邊界為 low,右邊界為 high,區間的中點為 pivot,最小值就在該區間內。我們將中軸元素 nums[pivot] 與右邊界元素 nums[high] 進行比較,可能會有以下的三種情況:

第一種情況是 nums[pivot]<nums[high]。如下圖所示,這說明 nums[pivot] 是最小值右側的元素,因此我們可以忽略二分查詢區間的右半部分。

第二種情況是 nums[pivot]>nums[high]。如下圖所示,這說明 nums[pivot] 是最小值左側的元素,因此我們可以忽略二分查詢區間的左半部分。

由於陣列不包含重複元素,並且只要當前的區間長度不為 1,pivot 就不會與 high 重合;而如果當前的區間長度為 1,這說明我們已經可以結束二分查找了。當二分查詢結束時,我們就得到了最小值所在的位置。

寫法一:

class Solution {
public:
    int findMin(vector<int>& nums) {
        int n = nums.size();
        int l = 0, r = n - 1;
        while(l < r) {
            int mid = l + r >> 1;
            if(nums[mid] > nums[r]) l = mid + 1;
            else r = mid;
        }
        return nums[l];
    }
};

寫法二:

class Solution {
public:
    int findMin(vector<int>& nums) {
        int n = nums.size();
        int l = 0, r = n - 1;
        while(l < r) {
            int mid = l + r >> 1;
            if(nums[mid] < nums[r]) r = mid;
            else l = mid + 1;
        }
        return nums[l];
    }
};