算法练习第49题-寻找旋转排序数组中的最小值 II

158 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情

一、题目

已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,4,4,5,6,7] 在变化后可能得到: 若旋转 4 次,则可以得到 [4,5,6,7,0,1,4] 若旋转 7 次,则可以得到 [0,1,4,4,5,6,7] 注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]] 。

给你一个可能存在 重复 元素值的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。

你必须尽可能减少整个过程的操作步骤。

 

示例 1:

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

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

作者:力扣 (LeetCode) 链接:leetcode.cn/leetbook/re… 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

二、思考

二分查找

# 这道题是153的升华版
# 首先还是先思考这个数组,这个数组分为三种情况,
# 第一种情况,就是nums[mid]小于nums[right],这说明什么问题呢,
# 这说明了nums[mid]是右区间的最小值,这时我们可以忽略了这部分区间
# 第二种情况是nums[mid]大于nums[right],从第一种情况对比,
# 这时得到的结果是最小值就在下标mid与right之间,这时我们可以定义最小的左区间的开始位置
# 开始位置为left = mid + 1
# 在153中,因为不存在重复元素,所以只要区间的长度为1时,就找到了当前最小值得位置
# 但是,现有的list中元素是存在重复的,那么就有一个问题了,就是相等的情况
# 因为nums[mid] 等于 nums[right],这时无法选择到底是left加还是right减
# 假设当前长度为2时,那么nums[mid]其实就是最小的值了,那么这样就可以忽略右区间了,因此right1

其他思路

例如sort排序,min取最小值等等

三、代码


nums = [11,13,15,17]
class Solution:
    def findMin(self, nums: List[int]) -> int:
        left, right = 0, len(nums) - 1
        while left < right:
            mid = left + ((right - left)//2)
            if nums[mid] < nums[right]:
                right = mid
            elif nums[mid] > nums[right]:
                left = mid + 1
            else:
                right -= 1
        return nums[left]

Solution().findMin(nums)

四、测试结果

image.png