[C++]LeetCode: 132 Find Minimum in Rotated Sorted Array II (二分查找)

题目:

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.

The array may contain duplicates.

思路:这道题是Search in Rotated Sorted Array的扩展。和Find Minimum in Rotated Sorted Array唯一的区别是,这都题目中会有重复的元素出现。在没有重复元素出现时,我们是根据边缘值和中间值比较确定,如何切掉一半元素的,如果加上了重复元素,我们无法判断哪边有序,哪边无序,也就无法确定元素之间的关系。假设原来的数组{1,2,3,3,3,3,3},旋转后得到{3,3,3,3,3,1,2}或者{3,1,2,3,3,3,3},这时我们判断时边缘和中间值都相等,我们并不知道应该截取哪一半,所以我们只能移动边缘一步,直到边缘和中间不在相等或者相遇。这就导致了最坏的情况下,可能每次都只移动一步,总共移动N次,算法的复杂度变成O(N).

这里我们还需要注意一个问题,我们利用右边缘和中间值来作比较,如果A[MID] == A[HI],我们移动HI一步,HI--. 这样最后返回A[lo]就是正确的最小值。但是如果使用左边缘来判断,由于除法的截断性,出现lo == mid, 导致A[lo] == A[mid], 如果我们移动下界lo++, 可能会跳过最小值。如数组{1,3},最后结果会返回A[lo] = 3. 上界hi就不会受到除法的截断性的影响,出现相等,就是遇到了重复元素这种情况,我们移动hi,不会影响结果。

二分查找思想并不难,可是实现过程中,需要反复考虑多种情况,主要要处理好细节。

复杂度:O(N)

Attention:

1. 移动上界,用上界来判断。

AC Code:

class Solution {
public:
    int findMin(vector<int> &num) {
        int lo = 0;
        int hi = num.size() - 1;
        int mid = 0;
        
        while(lo < hi)
        {
            int mid = lo + (hi - lo) / 2;
            
            if(num[hi] < num[mid])
            {
                lo = mid + 1;
            }
            else if(num[hi] > num[mid])
            {
                hi = mid;
            }
            else
            {
                hi--;
            }
        }
        return num[lo];
    }
};
面试中这种问题比较常见,现在的趋势是面试官从一个问题出发,然后follow up一些扩展的问题,而且这些问题一般涉及复杂度的改变,所以是面试中的一道好题,更有可能出现,可以结合 Find Minimum in Rotated Sorted Array来复习。

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