【Python Leetcode】153. Find Minimum in Rotated Sorted Array

题目

Suppose an array of length n sorted in ascending order is rotated between 1 and n times. For example, the array nums = [0,1,2,4,5,6,7] might become:

  • [4,5,6,7,0,1,2] if it was rotated 4 times.
  • [0,1,2,4,5,6,7] if it was rotated 7 times.

Notice that rotating an array [a[0], a[1], a[2], …, a[n-1]] 1 time results in the array [a[n-1], a[0], a[1], a[2], …, a[n-2]].

Given the sorted rotated array nums of unique elements, return the minimum element of this array.

You must write an algorithm that runs in O(log n) time.

从小到大排列的数组在经过n次回转之后,以O(log n)复杂度找到其最小元素。每一次回转会将数组最后一个元素放入数组首位,其余元素顺次往后一位。

Constraints 条件限制:

  • n == nums.length
  • 1 <= n <= 5000
  • -5000 <= nums[i] <= 5000
  • All the integers of nums are unique.
  • nums is sorted and rotated between 1 and n times.

思路:二分法查找

O(log n)复杂度首先想到二分法。可将数组index与元素值的关系看作分段函数,在每一段上单调递增,且第二段函数的最大值小于第一段函数的最小值。
【Python Leetcode】153. Find Minimum in Rotated Sorted Array_第1张图片
设发f(m)为函数最小值。设a为查找窗口的左端,b为窗口右端(b>a),c为ab中值 (c=(a+b)/2)。讨论f( c)与f(a)及f(b)关系,则有:

  • 【情况一】f(a)
  • 【情况二】 f(a)>f( c)且f(b)>f( c): b与c在第二段函数上,a在第一段函数上,a
  • 【情况三】f(a)=b.
  • 【情况四】f(a)=f( c): 由于int类型整除的特性,当b-a<2时,a=c. 由于contraints里规定数组中元素unique,当且仅当a=c时f(a)=f( c).

初始,令a=0, b=n-1.

  • 【情况一】:将窗口左端缩小,a=c.

  • 【情况二】:将窗口右端缩小, b=c.

  • 【情况三】:在初始情况下出现f(a)

    • nums[0]<=nums[a]: 返回nums[0]
    • nums[0]>nums[a]: m>=b且窗口搜索不足以找出最小值,遍历b到n-1之间的元素返回最小值(一般仅需遍历1-2个元素)。
  • 【情况四】:比较f(a)与f(b)返回最小值即可。

代码如下:54ms (14.18%), 13.7mb(56.32%)

class Solution(object):
    def findMin(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        a = 0
        b = len(nums)-1
        c = (b+a)/2
        
        if nums[a] < nums[c] and nums[c] < nums[b]:
            return nums[a]
        
        while True:
            if nums[a] < nums[c] and nums[b]<nums[c]:
                a = c
                c = (b+a)/2
            elif nums[a] > nums[c] and nums[b]>nums[c]:
                b = c
                c = (b+a)/2
                
            elif nums[a] < nums[c] and nums[c] < nums[b]:
                if nums[0]<= nums[a]:
                    return nums[0]
                else:
                    min = nums[a]
                    for i in range(b, len(nums)-1):
                        if nums[i]<min:
                            min = nums[i]
                            
                    return min
            elif a==c:
                if nums[a]<nums[b]:
                    return nums[a]
                else:
                    return nums[b]
            else:
                return nums[a]

以下是类似思路,但将n=2,3的情况单独讨论的代码,时间缩短近40%.(31ms, 76.18%; 13.7mb, 56.32%)

class Solution(object):
    def findMin(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        a = 0
        b = len(nums)-1
        c = (b+a)/2
        
        if nums[a] <= nums[b]:
            return nums[a]
        elif b>0 and b<3:
            if nums[b-1]>nums[b]:
                return nums[b]
            else:
                return nums[b-1]
        
        while True:
            if nums[c] > nums[a]:
                a = c
                c = (b+a)/2
            elif c>=1 and nums[c]<nums[c-1]:
                return nums[c]
            else:
                c -= 1
                if c <= 0:
                    if nums[c]<nums[b]:
                        return nums[0]
                    else:
                        return nums[b]

由于最小值是唯一不满足单调性的解,也可以利用这一特性判断何时返回 (来自官方解法思路)(38ms, 55.3%; 13.9mb, 9.38%):

class Solution(object):
    def findMin(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        a = 0
        b = len(nums)-1
        c = (b+a)/2
        
        if nums[a] <= nums[b]:
            return nums[a]
        elif b>0 and b<3:
            if nums[b-1]>nums[b]:
                return nums[b]
            else:
                return nums[b-1]
        
        while b > a:
            if nums[c]>nums[c+1]:
                return nums[c+1]
            if nums[c] > nums[a]:
                a = c
                c = (b+a)/2
            else:
                b = c
                c = (b+a)/2
                
        return nums[c]

你可能感兴趣的:(python,leetcode,leetcode,算法,python)