寻找旋转排序数组中的最小值 II

寻找旋转排序数组中的最小值 II

1.题目描述

假设按照升序排序的数组在预先未知的某个点上进行了旋转。( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。请找出其中最小的元素。注意数组中可能存在重复的元素。
示例 1:
在这里插入图片描述
示例 2:
在这里插入图片描述

2.思路(二分搜索)

1.旋转排序数组 nums 可以被拆分为 2 个排序数组 nums1, nums2 ,并且 nums1任一元素 >= nums2任一元素;因此,考虑二分法寻找此两数组的分界点 nums[i] (即第 2 个数组的首个元素)。
2.设置 left, right 指针在 nums 数组两端,mid 为每次二分的中点:
(1)当 nums[mid] > nums[right]时,mid 一定在第 1 个排序数组中,i 一定满足 mid < i <= right,因此执行 left = mid + 1。
(2)当 nums[mid] < nums[right] 时,mid 一定在第 2 个排序数组中,i 一定满足 left < i <= mid,因此执行 right = mid;
(3)当 n u m s [ m i d ] = = n u m s [ r i g h t ] nums[mid] == nums[right] 时,此题中数组的元素可重复,难以判断分界点 i 指针区间:
1)例如[1,0,1,1,1] 和 [1,1,1,0,1] ,在 left = 0, right = 4, mid = 2 时,无法判断 mid 在哪个排序数组中。
2)我们采用 right = right - 1 解决此问题,证明:
此操作不会使数组越界:因为迭代条件保证了 right > left >= 0;
此操作不会使最小值丢失:假设 nums[right] 是最小值,有两种情况:
若 nums[right] 是唯一最小值:那就不可能满足判断条件 n u m s [ m i d ] = = n u m s [ r i g h t ] nums[mid] == nums[right] ,因为 mid < right(left != right 且 mid = (left + right) // 2 向下取整);
若 nums[right] 不是唯一最小值,由于 mid < right 而 nums[mid] == nums[right],即还有最小值存在于 [left, right - 1]区间,因此不会丢失最小值。

3.代码

class Solution {
public:
    int findMin(vector<int>& nums) {
        int begin = 0;
        int end = nums.size() - 1;

        while(begin < end){
            int mid = (end + begin) / 2;
            if(nums[mid] > nums[end]){
                begin = mid + 1;
            }
            else if(nums[mid] < nums[end]){
                end = mid;
            }
            else{
                end = end - 1;
            }
        }
        return nums[begin];
    }
};

复杂度分析

时间复杂度:O(n)
空间复杂度:O(1)

发布了71 篇原创文章 · 获赞 0 · 访问量 785

猜你喜欢

转载自blog.csdn.net/jiangdongxiaobawang/article/details/103936522
今日推荐