返回
LeetCode 第 154 题:寻找旋转排序数组中的最小值 II
见解分享
2023-11-26 11:40:56
如何找到旋转排序数组中的最小值,即使有重复元素:一个逐步指南
简介
旋转排序数组是一种按升序排列的数组,被旋转了一次或多次,形成了一个“环”。当数组中存在重复元素时,找到最小值会变得更具挑战性。本文将深入探讨如何使用二分查找算法高效地解决这个棘手的问题。
二分查找算法
二分查找是一种通过将搜索空间一分为二来工作的搜索算法。对于旋转排序数组,我们需要考虑重复元素的影响。
分步指南
-
初始化变量:
- 设置数组的起始索引为
left = 0
。 - 设置数组的结束索引为
right = n-1
,其中n
是数组的长度。 - 将最小值设为正无穷大,即
min = float('inf')
。
- 设置数组的起始索引为
-
二分查找循环:
- 只要
left <= right
,执行以下步骤:- 计算中间索引
mid = (left + right) // 2
。 - 如果
nums[mid]
小于min
,则更新min
为nums[mid]
。 - 如果
nums[mid]
等于nums[right]
,说明右半部分存在重复元素,将right
减 1。 - 如果
nums[mid]
小于nums[right]
,说明最小值在右半部分,将left
设为mid + 1
。 - 如果
nums[mid]
大于nums[right]
,说明最小值在左半部分,将right
设为mid
。
- 计算中间索引
- 只要
-
返回最小值:
- 循环结束后,返回
min
。
- 循环结束后,返回
示例
考虑以下旋转排序数组:
nums = [3,4,5,1,2]
按照上述步骤进行二分查找:
- 初始化
left = 0
、right = 4
和min = float('inf')
。 - 计算
mid = 2
。nums[mid] = 5
,不更新min
。nums[mid]
等于nums[right]
,将right
减 1,现在right = 3
。 - 计算
mid = 2
。nums[mid] = 5
,不更新min
。nums[mid]
等于nums[right]
,将right
减 1,现在right = 2
。 - 计算
mid = 1
。nums[mid] = 4
,不更新min
。nums[mid]
小于nums[right]
,将left
设为mid + 1
,现在left = 2
。 - 计算
mid = 2
。nums[mid] = 5
,不更新min
。nums[mid]
等于nums[right]
,将right
减 1,现在right = 1
。 - 计算
mid = 1
。nums[mid] = 4
,不更新min
。nums[mid]
小于nums[right]
,将left
设为mid + 1
,现在left = 2
。 - 计算
mid = 2
。nums[mid] = 5
,不更新min
。nums[mid]
等于nums[right]
,将right
减 1,现在right = 0
。 - 计算
mid = 0
。nums[mid] = 3
,更新min
为 3。 - 返回
min = 3
。
代码实现
def findMin(nums):
left = 0
right = len(nums) - 1
min = float('inf')
while left <= right:
mid = (left + right) // 2
if nums[mid] < min:
min = nums[mid]
if nums[mid] == nums[right]:
right -= 1
elif nums[mid] < nums[right]:
left = mid + 1
else:
right = mid
return min
结论
使用二分查找算法可以高效地解决寻找旋转排序数组中最小值的问题,即使存在重复元素。该算法通过考虑重复元素的影响并使用适当的比较,可以收窄搜索空间并找到最小值。理解旋转排序数组以及解决类似问题对于实际应用至关重要。
常见问题解答
- 什么是旋转排序数组?
旋转排序数组是一种按升序排列的数组,被旋转了一次或多次,形成了一个“环”。
- 当数组中存在重复元素时,寻找最小值有什么困难?
重复元素使得难以确定哪个半部分包含最小值。
- 二分查找算法如何解决这个问题?
二分查找算法通过考虑重复元素的影响并使用适当的比较,可以收窄搜索空间。
- 代码示例中的
min
变量的作用是什么?
min
变量存储当前找到的最小值。
- 该算法的时间复杂度是多少?
该算法的时间复杂度为 O(log n),其中 n 是数组的长度。