leetcode【153,154】【tag array】Find Minimum in Rotated Sorted Array I / II【c++版本,二分查找,劍指offer,遞歸,非常簡潔】

問題描述(153):

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e.,  [0,1,2,4,5,6,7] might become  [4,5,6,7,0,1,2]).

Find the minimum element.

You may assume no duplicate exists in the array.

Example 1:

Input: [3,4,5,1,2] 
Output: 1

Example 2:

Input: [4,5,6,7,0,1,2]
Output: 0

源碼(153):

其實就是二分查找,但是一定要注意的就是R和L的處理,我們是把R=mid而L=mid+1。因爲當nums[i]<nums[R]的時候,mid處有可能是最小值,而反之L處不可能是最小值,所以等於mid+1。

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

如果硬要全部都是Mid的話,要考慮L可能永遠不等於R,此時加一句判斷,R-L==1。

也不知道爲啥空間這麼低,最近leetcode的空間一直都不高,前陣子一直都是100%時間不行,迷得不行。

class Solution {
public:
    int findMin(vector<int>& nums) {
        int L=0, R=nums.size()-1, mid=0;
        while(L<R){
            if(R-L==1)      return min(nums[R], nums[L]);
            mid = (R+L)/2;
            if(nums[mid]<nums[R])          R = mid;
            else                           L = mid;
        }
        return nums[L];
    }
};

問題描述(154):

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e.,  [0,1,2,4,5,6,7] might become  [4,5,6,7,0,1,2]).

Find the minimum element.

The array may contain duplicates.

Example 1:

Input: [1,3,5]
Output: 1

Example 2:

Input: [2,2,2,0,1]
Output: 0

Note:

源碼(154):

這題和《劍指offer》第二版面試題11是一樣的,我先展示一下書上的做法,當發現左右和中間的元素相等的時候,就需要線性遍歷了。

class Solution {
public:
    int find(vector<int>& nums, int L, int R){
        int result = nums[L];
        for(int i=L+1; i<=R; i++){
            result = min(result, nums[i]);
        }
        return result;
    }
    
    int findMin(vector<int>& nums) {
        int L=0, R=nums.size()-1, mid=0;
        if(R==0)    return nums[R];
        while(nums[L] >= nums[R]){
            if(R-L == 1)    return nums[R];
            mid = (L+R)/2;
            if(nums[mid]==nums[L] && nums[mid]==nums[R])   return find(nums, L, R);
            if(nums[mid] >= nums[L])        L = mid;
            else if(nums[mid] <= nums[R])     R = mid;
        }
        return nums[mid];
    }
};

自己調了半天的寫法,很挫,就是不想直接順序遍歷下去。

class Solution {
public:    
    int findMin(vector<int>& nums) {
        int L=0, R=nums.size()-1, mid=0;
        if(R==0)    return nums[R];
        int result = INT_MAX;
        while(nums[L] >= nums[R] && L<R){
            if(R-L == 1)    return nums[R];
            mid = (L+R)/2;
            if(nums[mid]==nums[L] && nums[mid]==nums[R]){
                L++;    R--;
                result = min(nums[L], nums[R]);
                continue;
            }
            else if(nums[mid] >= nums[L])        L = mid;
            else if(nums[mid] <= nums[R])     R = mid;
            result = min(result, nums[mid]);
        }
        return min(result,nums[mid]);
    }
};

把書上的寫法改成了遞歸(我自己的做法也可以改,讀者可以自己試着改一下,這裏我不展示了)

class Solution {
public: 
    int help(vector<int>& nums, int left, int right){
        int result = nums[left];
        for(int i=left+1; i<=right; i++){
            result = min(result, nums[i]);
        }
        return result;
    }
    int find(vector<int>& nums, int left, int right, int mid){
        if(nums[left]<nums[right])    return nums[mid];
        if(right-left==1)   return nums[right];
        mid = (left+right)/2;
        if(nums[mid]==nums[left] && nums[mid]==nums[right]){
            return help(nums, left, right);
        }
        else if(nums[mid]>=nums[left])      left = mid;
        else if(nums[mid]<=nums[right])     right = mid;
        return find(nums, left, right, mid);
    }
    int findMin(vector<int>& nums) {
        if(nums.size()==1)    return nums[0];
        return find(nums, 0 ,nums.size()-1, 0);
    }
};

 

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