题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
该数组中的重要数字特征为:非递减排序
首先,最简单的方式是
1、遍历算法
class Solution:
def minNumberInRotateArray(self, rotateArray):
# write code here
minNum = rotateArray[0]
for i in range(0,len(rotateArray)):
minNum = minNum if minNum < rotateArray[i] else rotateArray[i]
return minNum
时间复杂度为O(n)
然后,看能否进行优化。对于非递减的数列,可想到使用二分查找的思想进行数值查询。(二分查找:漫画:什么是二分查找)
而输入的数组却是非递减排序数组翻转之后的数组。
例如:
1 2 3 4 5 6 7 8 9==》 6 7 8 9 5 1 2 3 4
6 7 8 9 ==》8 9 6 7
对于反转后的情况讨论,
当为奇数位数组时,右半侧一定比中位数小,左右半侧均为非递减且右半侧均小于左半侧,因此左右半侧中的前一个数一定会比后一个数小;
当为偶数位数组时,右半侧比左半侧小,左右半侧均为非递减且右半侧均小于左半侧,因此左右半侧中的前一个数一定会比后一个数小。
根据这个特性,发现当找到的某个数比它的前一个数小时,说明是找到了翻转的分界点,且该数为原非递减数列的第一位数,可以确定该数一定为最小数。若不满足上述条件且该数比它的最右端数小,说明该数为右半侧数,由于为非递减排序最小值在该数左侧;反之,则说明该数为左半侧书,最小值应为应为数列的右半侧在它的右侧。
2、二分查找搜索
class Solution:
def minNumberInRotateArray(self, rotateArray):
# write code here
# 数组为空时返回0
if not rotateArray:
return 0
low = 0
high = len(rotateArray)-1
while low <= high:
mid = (low + high) // 2 # 除以2时向下取值
if rotateArray[mid] < rotateArray[mid-1]:
return rotateArray[mid]
elif rotateArray[mid] < rotateArray[high]:
high = mid - 1
else:
low = mid + 1
return 0
时间复杂度为O(logn)