接昨天的“153. 寻找旋转排序数组中的最小值”,题目与153大致相同,只是将之前数组中没有重复元素这个条件换成了有重复数组的,所以解法大致相同。
具体看题目https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array-ii/
最最简便的方法就是从头到尾遍历整个数组,比较第i个元素与第i+1个元素的值,若第i个元素比第i+1个大,说明找到了这个最小元素,返回即可,若是遍历完仍是没有这个情况出现,说明数组内元素当前是从小到大有序的,即第一个元素是它的最小元素。具体代码如下:
class Solution:
def findMin(self, nums: List[int]) -> int:
for i in range(len(nums)-1):
if nums[i] > nums[i+1]:
return nums[i+1]
return nums[0]
当然,这个也是可以使用二分查找的,即通过对数组中每两个元素之间的位置进行查找,找到一个位置,它的两边的元素左边的大于右边的即可。
对于有n个元素的数组,其中有n-1个位置,对这n-1个位置进行二分查找,找到则返回结果,没找到(最坏情况:数组内元素是从小到大有序的)则跟前面方法一样,返回它的第一个元素。
一般情况下,它的时间复杂度为O(logn),比前面顺序的算法复杂度O(n)要好一些。
最坏情况下,即数组元素是从小到大排好序的,此时时间复杂度等于顺序查找的情况,O(n)。
代码如下:
class Solution:
def findMin(self, nums: List[int]) -> int:
def sepFind(i, j):
if i == j:
return None if nums[i]<= nums[i+1] else nums[i+1]
mid = int(i + j)//2
if nums[mid] > nums[mid+1]:
return nums[mid+1]
r1 = sepFind(i, mid)
r2 = sepFind(mid+1, j)
if r1 is None:
return r2
else:
return r1
l = len(nums)
if l == 1:
return nums[0]
minx = sepFind(0, l-2)
if minx is None:
return nums[0]
else:
return minx