[C++]LeetCode: 80 Find Minimum in Rotated Sorted Array

题目:

Suppose a sorted array 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.

思路:

[C++]LeetCode: 80 Find Minimum in Rotated Sorted Array_第1张图片

考虑我们将序列分成两部分,一部分将会是有序的,另外一部分包含最小值。

举例子,一个数字[1,2,3,4,5,6,7](图1), 从离最右值三步的位置旋转,得到[5,6,7,1,2,3,4](图2),假设我们将序列从距离左边k步的位置旋转,得到子序列[AL, AL+1, …, Ak], [Ak+1, …, AR].

迭代条件:

(1)如果有序序列并未被旋转,即AL < AR, 那么AL就是最小值,返回AL;

(2)如果有序序列至少被旋转一步,那么AL必定比AR大;

         让我们假设M1是切割点(MID),因为AM1>AR,并且在[AL … AM1]中的每一个元素都大于AR(因为AL>AR,且序列递增),则最小值会在[AM1+1 … AR]中间。(start = mid + 1;)

另外一种情况,如果选择M2为切割点(MID),因为AM2 <=AR, 我们知道[AM2+1 … AR] 中的每一个元素都比AM2大(递增),则最小值在[AL … AM2]中间。(end = mid;)

终止条件:

给出两个例子:A = [1,2] ; B = [2,1]

For A, 1 < 2 => AM < AR, and therefore it will set R = M => R = 0.

For B, 2 > 1 => AM > AR, and therefore it will set L = M + 1 => L = 1.

当L == R时,迭代结束,我们找到最小值,所以循环外条件(start < end),不能取等号。

Attention:

1. 迭代终止条件 start == end, 则循环条件不能取等号

 while(start < end)
2. 判断从start到end是有序序列,则可以直接返回start.

/start到end是有序序列 start是最小值; 由于只旋转一次,start和end之间不会出现更低的值
            if(num[start] < num[end])
            {
                return num[start];
            }
3. 注意根据上面的分析,确定每个迭代的条件和区间的确定,是否包含mid都要注意。

//start到end不满足有序 继续查找较小半部分 最小值在右半部分
            if(num[start] <= num[mid])
            {
                start = mid + 1;  //num[mid] >= num[start] >= num[end] ,则mid一定不是最小值 可以跳过
            }
            else
            {
                end = mid;      //num[mid] < num[start], mid有可能是最小值,不能跳过。
            }

复杂度:O(log(n))

AC Code:

class Solution {
public:
    int findMin(vector<int> &num) {
        int n = num.size();
        if(n == 0) return 0;
        
        int start = 0;
        int end = n - 1;
        
        while(start < end)
        {
            int mid = start + (end - start)/2;
            //start到end是有序序列 start是最小值; 由于只旋转一次,start和end之间不会出现更低的值
            if(num[start] < num[end])
            {
                return num[start];
            }
            
            //start到end不满足有序 继续查找较小半部分 最小值在右半部分
            if(num[start] <= num[mid])
            {
                start = mid + 1;  //num[mid] >= num[start] >= num[end] ,则mid一定不是最小值 可以跳过
            }
            else
            {
                end = mid;      //num[mid] < num[start], mid有可能是最小值,不能跳过。
            }
        }
        
        return num[start];
    }
};


你可能感兴趣的:(LeetCode,array,search,binary)