leetcode. 旋转数组的最小数字

题目描述:

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。  

示例 1:

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

输入:[2,2,2,0,1]
输出:0

解题思路:

方法一:线性查找(暴力解法)

         易知最小值所在的地方一定是数值阶跃的位置,因此可以直接对数组进行线性查找,若某处值小于前一个值,则该值即为数组最小值。

class Solution(object):
    def minArray(self, numbers):
        """
        :type numbers: List[int]
        :rtype: int
        """
        '''
        线性查找
        '''
        pre=numbers[0]
        for num in numbers:
            if num<pre:
                return num
            pre=num
        return numbers[0]

方法二:二分查找

考虑数组中的最后一个元素 x:在最小值右侧的元素,它们的值一定都小于等于 x;而在最小值左侧的元素,它们的值一定都大于等于 x。因此,我们可以根据这一条性质,通过二分查找的方法找出最小值。

在二分查找的每一步中,左边界为low,右边界为high,区间的中点为 pivot,最小值就在该区间内。我们将中轴元素 numbers[pivot] 与右边界元素numbers[high] 进行比较,可能会有以下的三种情况:

  1. 第一种情况是 numbers[pivot] < numbers[high],这说明 numbers[pivot]是最小值右侧的元素,因此我们可以忽略二分查找区间的右半部分。
  2. 第二种情况是 numbers[pivot] > numbers[high],这说明 numbers[pivot]是最小值左侧的元素,因此我们可以忽略二分查找区间的左半部分。
  3. 第三种情况是 numbers[pivot]==numbers[high]。如下图所示,由于重复元素的存在,我们并不能确定 numbers[pivot] 究竟在最小值的左侧还是右侧,因此我们不能莽撞地忽略某一部分的元素。我们唯一可以知道的是,由于它们的值相同,所以无论 numbers[high] 是不是最小值,都有一个它的「替代品」numbers[pivot],因此我们可以忽略二分查找区间的右端点。

class Solution(object):
    def minArray(self, numbers):
        """
        :type numbers: List[int]
        :rtype: int
        """
       
        '''
        二分查找
        '''
        low,high=0,len(numbers)-1
        while low<high:
            mid=low+(high-low)/2  #这里不写成(low+high)/2是为了防止溢出
            #如果中间值大于最右端值,则最小值在右部分区间
            if numbers[mid]>numbers[high]:    
                low=mid+1
             #如果中间值小于最右端值,则最小值在左部分区间
            elif numbers[mid]<numbers[high]:
                high=mid  #注意这里high=mid而不是mid-1因为mid出也可能是最小值
            else:
                high-=1
        return numbers[low]

trick:mid=low+(high-low)/2不写成mid=(high+low)/2是为了防止溢出

由于数据问题该题使用暴力解法耗时更短

猜你喜欢

转载自blog.csdn.net/qq_36854740/article/details/107521593