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

题目描述

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

示例 1:
输入: [1,3,5]
输出: 1

示例 2:
输入: [2,2,2,0,1]
输出: 0
说明:
这道题是 寻找旋转排序数组中的最小值 的延伸题目。允许重复会影响算法的时间复杂度吗?会如何影响,为什么?

代码

class Solution {
public:
    int findMin(vector<int>& nums) {

    	int n = nums.size();
    	if(n == 0)
    		return INT_MAX;
    	if(n == 1)
    		return nums[0];
    	int l = 0;
    	int h = n-1;
    	while(l <= h)
    	{
    		if(h-l == 0 || h-l == 1)
    			return min(nums[l],nums[h]);
    		else
    		{
                //这两行代码可以去掉,程序依然正确,加上这两行代码,可以使程序在已经可以停止时及时停止
    			// if(nums[h] > nums[l])
                //     return nums[l];

                //根据nums[mid]是处于前半段,还是后半段,来决定查找范围的转向
    			int mid = l+(h-l)/2;
                //由于我们是根据nums[l],nums[h],nums[mid]之间的大小关系,来判断nums[mid]是位于前半部分,还是后
                //半部分,当这个条件发生时(由旋转的特点,当由搜索范围是两段时,总会有nums[l]>=nums[h],整个前半段
                //总是大于等于后半段,由这个特点,即使发生nums[l]==nums[h]!=nums[mid],我们依然能够确定nums[mid]的位置),
                
                //我们无法判断nums[mid]的位置
	    		if(nums[mid]==nums[l] && nums[mid]==nums[h])
	    		{   
                    
	    			l++;
	    			h--;//这时不会发生遗漏,至少还有mid,这里范围已经确保至少有三个数,所以可以大胆的去掉
	    		}
	    		else
	    		{
	    			//这个条件要放在前面,因为可能出现0旋转的情况,
	                //或者已经是一个有序的情况,而我们要找的是最小
	                //元素,把这个条件放在前面,是为了向最小元素方向
	                //跳转
	    			if(nums[mid]<=nums[h])
	    				h = mid;
	    			else if(nums[mid]>=nums[l])
	    				l = mid;
	    			
	    		}
	    	}
    	}
    	return INT_MAX;       
    }
};

posted on 2021-05-01 19:46  朴素贝叶斯  阅读(31)  评论(0编辑  收藏  举报

导航