153. Find Minimum in Rotated Sorted Array

Problem

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.

You may assume no duplicate exists in the array.
  • python内置函数min(nums),显然这么解不是本题原意
  • 有次序的列表旋转特性:第一个小于尾字符的字符即为旋转点(二分用不到,遍历可用)
  • 旋转点比左/右边界都小(二分)
  • 二分应该优于遍历查找

solution

无其他库版本

class Solution(object):
    def findMin(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        right = len(nums)-1
        left = 0 
        while left < right:
            if nums[left] <= nums[right]:
                return nums[left]
            mid = (left + right)/2
            if nums[mid] > nums[right]:
                left = mid + 1
            else:
                right = mid
        return nums[left]
        
            if nums[left] <= nums[right]:
                return nums[left]

其中这段不是标准的二分,逻辑比较难理解,可以提高执行效率

  1. 如果是空元素,单元素,无旋转序列直接给出结果
  2. 每次切分后,根据特性做一个判断,如果left已经到达旋转点,则返回

如何确认return时left元素刚好位于旋转点,而不是旋转点后?

此前left右移,left = mid + 1
此时left左边相邻元素为mid元素,已经通过游标右移判断nums[mid] > nums[right],left即为旋转点

nums[mid] > nums[right]

nums[left] = nums[mid+1] <= nums[right]

此前right左移,right = mid ,左移前提nums[mid] <= nums[right], 由于旋转特性right左移范围不会越过旋转点,(其实left右移同样不会越过)

旋转点左边的值肯定大于右边的值,这一特性可以推导出,right左移不会越过旋转点(right =mid,只有mid<= right的时候才可左移),left右移同样不会(left = mid +1, 只有在mid>right的时候才可右移)

discuss solution

class Solution:
    def findMin(self, nums):
        self.__getitem__ = lambda i: nums[i] <= nums[-1]
        return nums[bisect.bisect(self, False, 0, len(nums))]

炫技写法

getitem 鸭子类型,列表特性

此时self[i] = True/False

此时solution instance 具有列表部分特性 , 类似的格式为[False,False,False,True,True,True]

len(nums) 没用默认参数是因为此时,solution instance 还没有 len 方法

https://docs.python.org/2/library/bisect.html

bisect.bisect(a, x, lo=0, hi=len(a))
Similar to bisect_left(), but returns an insertion point which comes after (to the right of) any existing entries of x in a.

The returned insertion point i partitions the array a into two halves so that all(val <= x for val in a[lo:i]) for the left side and all(val > x for val in a[i:hi]) for the right side.

posted @ 2016-09-27 21:12  Salmd  阅读(173)  评论(0)    收藏  举报