[LeetCode]111. Find Minimum in Rotated Sorted Array II旋转数组最小值II

Follow up for "Find Minimum in Rotated Sorted Array":
What if duplicates are allowed?

Would this affect the run-time complexity? How and why?

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.

解法1:本题旋转数组最小值的扩展,这次数组中可以存在重复元素了。上题因数组中无重复元素,因此通过判断nums[left]和nums[mid]的大小可以确定[left,mid]之间是否是严格递增的,而当存在重复元素时就不能这样简单的确定了。比如数组{0,1,1,1,1}的两种旋转{1,0,1,1,1}和{1,1,1,0,1},第一次迭代时nums[left]=nums[mid]=nums[right],这样不能确定不能确定[left,mid)或者(mid,right]是不是升序,也不知道最小元素0是在[left,mid]还是[mid,right]之中。因此当left、mid、right三者所指数组元素相同时调用顺序查找算法。

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

解法2:当left、mid、right三者所指数组元素相同时,可以将left右移一位,跳过这个相同元素,这样并不会影响结果,因为这个元素还有另外的副本存在与剩下的数组中。注意输入数组有两种情况:要么nums[left]<nums[right],此时数组未被旋转,可以直接返回;要么nums[left]>=nums[right],这时数组被旋转过。

class Solution {
public:
    int findMin(vector<int>& nums) {
        int n = nums.size(), left = 0, right = n - 1, mid = 0;
        if (n == 0) return 0;
        while (left < right) {
            if(nums[left] < nums[right]) return nums[left];
            mid = (left + right) >> 1;
            if (nums[left] < nums[mid])
                left = mid + 1;
            else if (nums[left] > nums[mid])
                right = mid;
            else ++left;
        }
        return nums[right];
    }
};
原文地址:https://www.cnblogs.com/aprilcheny/p/5047504.html