LeetCode 153. Find Minimum in Rotated Sorted Array 题解
LeetCode 153. Find Minimum in Rotated Sorted Array 题解
题目描述
已知一个长度为n的数组,预先按照升序排列,经由1到n次旋转后,得到输入数组。例如,原数组nums = [0,1,2,4,5,6,7]在变化后可能得到:
- 若旋转
4次,则可以得到[4,5,6,7,0,1,2] - 若旋转
7次,则可以得到[0,1,2,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 = [3,4,5,1,2] 输出:1 解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。示例 2:
输入:nums = [4,5,6,7,0,1,2] 输出:0 解释:原数组为 [0,1,2,4,5,6,7] ,旋转 4 次得到输入数组。示例 3:
输入:nums = [11,13,15,17] 输出:11 解释:原数组为 [11,13,15,17] ,旋转 4 次得到输入数组。解题思路
方法:二分查找
思路:
- 由于数组是旋转排序的,所以数组可以分为两部分,每部分都是升序的,且前一部分的所有元素都大于后一部分的所有元素。
- 我们可以使用二分查找来快速定位最小元素。
- 具体步骤:
- 初始化左指针
left为 0,右指针right为数组长度减 1。 - 当
left < right时,计算中间位置mid。 - 比较
nums[mid]和nums[right]的大小:- 如果
nums[mid] < nums[right],说明最小元素在左侧,将right设为mid。 - 如果
nums[mid] > nums[right],说明最小元素在右侧,将left设为mid + 1。
- 如果
- 当
left == right时,返回nums[left],此时left指向最小元素。
- 初始化左指针
复杂度分析:
- 时间复杂度:O(log n),其中 n 是数组的长度。每次查找都会将查找区间减半。
- 空间复杂度:O(1),只需要常数级的额外空间。
代码实现
方法:二分查找
class Solution: def findMin(self, nums: List[int]) -> int: # 初始化左指针和右指针 left = 0 right = len(nums) - 1 # 当左指针小于右指针时,继续查找 while left < right: # 计算中间位置 mid = left + (right - left) // 2 # 比较中间元素和右指针元素的大小 if nums[mid] < nums[right]: # 最小元素在左侧,将右指针移到中间位置 right = mid else: # 最小元素在右侧,将左指针移到中间位置的右边 left = mid + 1 # 当左指针等于右指针时,返回左指针指向的元素,此时左指针指向最小元素 return nums[left]测试用例
测试用例 1:
输入:nums = [3,4,5,1,2]
输出:1
测试用例 2:
输入:nums = [4,5,6,7,0,1,2]
输出:0
测试用例 3:
输入:nums = [11,13,15,17]
输出:11
总结
本题是二分查找的经典变体问题,主要考察对二分查找算法的理解和应用。通过比较中间元素和右指针元素的大小,我们可以确定最小元素的位置在左侧还是右侧,从而缩小查找区间。
二分查找的核心思想是:使用两个指针分别指向查找区间的两端,计算中间位置,比较中间元素与目标值的大小,根据比较结果缩小查找区间,直到找到目标值或确定目标值不存在。
这种方法的时间复杂度为 O(log n),适用于大规模旋转排序数组的最小元素查找。掌握二分查找的原理,对于理解搜索算法和算法设计思想非常重要。
