154寻找旋转排序数组中的最小值Ⅱleetcode

难度系数:困难
题目:假设按照升序排序的数组在预先未知的某个点上进行了旋转。

( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

请找出其中最小的元素。

注意数组中可能存在重复的元素。

示例 1:

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

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

说明:
这道题是 寻找旋转排序数组中的最小值 的延伸题目。
允许重复会影响算法的时间复杂度吗?会如何影响,为什么?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

这道题目是153寻找旋转排序数组中的最小值的允许有重复元素的版本。可以先做做153题。
——————————我时分割线——————————
解法:
思路:二分法 + 末尾去重

令数组最后一个元素为x,则:
最小值右侧的元素均小于x;
最小值左侧的元素均大于x。
(例:[5,6,7,2,3,4],x=4。最小值为2,2右侧元素3小于4;2左侧元素5,6,7大于4)

在二分法的每一步,令左边界为left,右边界为right,区间的中点为mid。将中间元素nums[mid]和最右边的元素nums[right]比较,会出现以下三种情况:
1.nums[mid] < nums[right],说明最小值在mid左侧,故可忽略mid右边的元素。
2.nums[mid] > nums[right],说明最小值在mid右侧,故可忽略mid左边的元素。
3.nums[mid] == nums[right],由于数组中存在重复的元素,故无法确定最小值在mid左侧还是右侧,故不可忽略任何一部分的元素。但是因为nums[mid]==nums[right],故无论它是否为最小值,均有mid这个重复值,故可忽略右端点right。right-=1.

二分结束,可得最小值的位置。

代码:

# leetcode154寻找旋转排序数组中的最小值Ⅱ (重复元素)
class Solution(object):
    def findMin(self, nums):
        left = 0 #左节点 指向第一个元素
        right = len(nums)-1 #右节点 指向最后一个元素

        while left<right:
            mid = left+(right-left)//2 #找到中间节点(这样写是以防right过大溢出)
            if nums[mid]<nums[right]: #最小值在mid左边
                right = mid #忽略右边
            elif nums[mid]>nums[right]: #最小值在mid右边
                left = mid+1 #忽略左边
            else: #nums[mid]==nums[right] 可忽略right
                right -= 1
        return nums[left]
# nums = [3,4,5,1,2]
nums = [2,2,2,0,1] #0
print(Solution().findMin(nums))

154寻找旋转排序数组中的最小值Ⅱleetcode_第1张图片

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