153. Find Minimum in Rotated Sorted Array
题目描述
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]).
Find the minimum element.
You may assume no duplicate exists in the array.
解题思路
一个简单的暴力解法就是遍历整个数组, 比较后一个数是否小于前一个数. 时间复杂度是O(N). 贴一下代码:
def findMin(nums):
for i in range(len(nums)-1):
if nums[i] > nums[i+1]:
return nums[i+1]
# 所有数都比下一个数小, 那么数列是递增, 返回第一个数
return nums[0]
但是这里我们讨论的是使用二分查找法来更高效地解决问题, 时间复杂度为O(logN) .通过二分查找法找到中值并以此决定在左半部分还是右半部分继续搜索. 因为原数组是有序的, 因此可以使用二分查找法, 但是数组被旋转了, 所以要稍微改改.
首先我们判断nums的首尾元素, 如果nums[head] < nums[tail], 说明数组没有被旋转过. 直接返回第一个元素即可.
如果nums[head] > nums[tail], 说明数组一定在某个位置存在inflection point, 在该值处数字由最大值到最小值(如图).
该点左边的数都比该点右边的数大. 因此每次找到中间值, 只要和nums[head]比较即可, 如果大于它, 说明中间值在inflection point的左边, 小于说明在右边.
具体算法是
-
Find the mid element of the array.
-
If mid element > first element of array this means that we need to look for the inflection point on the right of mid.
-
If mid element < first element of array this that we need to lookfor the inflection point on the left of mid.
-
We stop our search when we find the inflection point, when
either of the two conditions is satisfied:nums[mid] > nums[mid + 1] Hence, mid+1 is the smallest.
nums[mid - 1] > nums[mid] Hence, mid is the smallest.
代码
Python
class Solution:
def findMin(self, nums: List[int]) -> int:
if len(nums) == 1:
return nums[0]
# 比较首尾元素, 判断是否选择过.
if nums[0] < nums[len(nums)-1]:
return nums[0]
left = 0
right = len(nums)-1
while right >= left:
mid = left + (right - left) // 2
# 终止条件是当前一个数大于后一个数, 返回后一个数
if nums[mid] > nums[mid + 1]:
return nums[mid + 1]
if nums[mid-1] > nums[mid]:
return nums[mid]
# 将中间值同第一个数比较, 如果大于, 那么最小值在中间值右边, left=mid+1. 反之亦然.
if nums[mid] > nums[0]:
left = mid + 1
else:
right = mid - 1