https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof/
-
我第一时间想到的方法,遍历(估计是面试不能过系列)
思路:因为是递增数组旋转,旋转后为两个递增数组的拼接,则最小值一定是数组的第一个元素(未旋转),或数组后面小于数组第一个元素的第一个元素。
时间复杂度O(n),空间复杂度O(1)class Solution(object): def minArray(self, numbers): """ :type numbers: List[int] :rtype: int """ if len(numbers) == 0: return -1 result = numbers[0] for i in range(1, len(numbers)): if numbers[i] < result: result = numbers[i] break return result
-
python真的是一门好语言
class Solution(object): def minArray(self, numbers): """ :type numbers: List[int] :rtype: int """ return min(numbers)
-
二分法,时间复杂度降低为O(logn) 这个应该是面试官想要的
思路:判断数组中间元素与数组首位,末尾元素大小关系
因为翻转后的数组中所有元素必都小于翻转点元素,则
a. 判断若末尾元素大于首位元素,则数组未进行翻转。注意等于情况不能确定,譬如3,1,3
b. 判断末尾元素小于首位元素,则判断数组进行了翻转。需要找到翻转数组的开始节点
1. 如果中间节点大于首节点,则最小元素一定在【中间节点-尾节点】之间
2. 如果中间节点小于首节点,则最小节点一定在【首节点-中间节点】之间
3. 如果中间节点等于首节点,这个情况比较复杂,主要是要考虑到
1)若中间节点等于首节点小于尾节点,则为首节点小于尾节点情况,直接返回首节点
2)若中间节点大于尾节点,则最小数在中间节点和尾节点之间
3)若中间元素等于尾节点,譬如3,1,3,3,3,或3,3,3,1,3,无法判断最小值位置,则收缩方式改为忽略数组的首节点,因为首节点与中间节点值相同,忽略首节点不会导致最小值被忽略。递归法
class Solution(object): def minArray(self, numbers): """ :type numbers: List[int] :rtype: int """ if len(numbers) == 0: return -1 if len(numbers) == 1: return numbers[0] if len(numbers) == 2: if numbers[0] < numbers[1]: return numbers[0] else: return numbers[1] if numbers[-1] > numbers[0]: return numbers[0] mid = len(numbers) / 2 if numbers[mid] > numbers[0]: return self.minArray(numbers[mid+1:]) elif numbers[mid] < numbers[0]: return self.minArray(numbers[0:mid+1]) else: return self.minArray(numbers[1:]) return -1
耗时比第一种直接遍历都要长,呵呵哒了,递归真心不推荐,但是代码写出来是真的好看
迭代法
边界地方尤其麻烦,需要找几种例子画一画,不然很容易写错class Solution(object): def minArray(self, numbers): """ :type numbers: List[int] :rtype: int """ if len(numbers) == 0: return -1 if len(numbers) == 1: return numbers[0] if len(numbers) == 2: if numbers[0] < numbers[1]: return numbers[0] else: return numbers[1] if numbers[-1] > numbers[0]: return numbers[0] begin = 0 end = len(numbers) - 1 mid = end / 2 while (end - begin) > 1: if numbers[end] > numbers[begin]: return numbers[begin] if numbers[mid] > numbers[begin]: begin = mid + 1 mid = (begin + end) / 2 elif numbers[mid] < numbers[begin]: end = mid mid = (begin + end) / 2 else: begin = begin + 1 mid = (begin + end) / 2 if end == begin: return numbers[begin] else: if numbers[end] > numbers[begin]: return numbers[begin] else: return numbers[end] return -1
怎么说呢,废了半天劲