leetcode【中等】153、寻找旋转排序数组中的最小值

在这里插入图片描述
思路一:二分查找

  • 最小值即旋转点,旋转点左边的数都大于nums[0],右边都小于nums[0]
  • 取mid,若mid大于数组第一个数,即左半边是顺序,在右边寻找旋转点,否则在左边寻找
class Solution:
    def findMin(self, nums: List[int]) -> int:
        if len(nums)==1:
            return nums[0]
        left,right=0,len(nums)-1
        #右边数大于第一个数,说明有序
        if nums[right]>nums[0]:
            return nums[0]

        while left<=right:
            mid = left + (right - left) // 2
            # mid左右存在逆序
            if nums[mid]>nums[mid+1]:
                return nums[mid+1]
            if nums[mid-1]>nums[mid]:
                return nums[mid]
            #左边顺序,在右边找
            if nums[mid]>nums[0]:
                left=mid+1
            # 否则在左边找
            else:
                right=mid-1

思路二:优化(快很多)
合并一些情况,只和最右值对比:
如果中值 < 右值,右边顺序,则最小值在左半边,可以收缩右边界。
[1,(2),3,4] [3,4,5,(1),2]
如果中值 > 右值,左边顺序则最小值在右半边,可以收缩左边界。
[3,4,(5),1,2]

class Solution:
    def findMin(self, nums: List[int]) -> int:
        left, right = 0, len(nums) - 1
        while left < right:
            mid = (left + right) // 2
            if nums[mid] > nums[right]:
            	# 因为中值 > 右值,中值肯定不是最小值,左边界可以跨过mid	
                left = mid + 1 
            else:
           		# 因为中值 < 右值,中值也可能是最小值,右边界只能取到mid处
                right = mid 
        return nums[left]

也可以通过比较mid与left来解决问题。

不直接找最小值,而是先找最大值,最大值向右移动一位就是最小值了(需要考虑最大值在最右边的情况,右移一位后对数组长度取余)。

最大值偏右,可以通过比较mid与left来找到最大值,。

class Solution:
    def findMin(self, nums: List[int]) -> int:
        left, right = 0, len(nums) - 1   
        while left < right:          
            mid = (left + right + 1) //2
            #中值大于左值,左边顺序,在右边寻找,不能跨越mid         
            if nums[left] < nums[mid]:         
                left = mid                          
            elif nums[left] > nums[mid]:       
                right = mid - 1                     
        return nums[(right + 1) % len(nums)]       

猜你喜欢

转载自blog.csdn.net/qq_40707462/article/details/114028525