找出旋转数组中的最小元素
题:输入一个有序数组的旋转数组,要求输出旋转数组的最小值。
我们需要关注以下问题:
1.首先理解一下什么是旋转数组,设arr1 = []int{1,2,3,4,5,5}
,旋转值为2,则其旋转数组为[]int{3,4,5,5,1,2}
。可以理解为数组arr=[arr1,arr2]旋转后变为[arr2,arr1]
2.因为是一个有序数组的旋转,我们可以发现旋转后数组不再是单调递增而是先增到最大值突然下降到最小值然后再递增,其最小值在峰值之后。
3.考虑到数组几种比较特殊或者说是极端的情况:
- 数组所有元素都相同
- 数组大部分元素都相同
我们考虑用二分法找到最小值,下面简要介绍一下思路:
low,high分别代表数组第一个元素和最后一个元素的下标,mid=(low+high)/2。一个递增的数组旋转后正常情况下最后一个元素会<=第一个元素,以上述给出的数组为例,若
arr[mid-1]>arr[mid]
那么arr[mid]一定就是最小值,因为上边提到过"旋转后数组不再是单调递增而是先增到最大值突然下降到最小值然后再递增,其最小值在峰值之后。"arr[mid]>arr[mid+1]
,则arr[mid+1]是最小值- 如果以上两点都不满足,
arr[mid]>arr[high]
那么最小值在mid右半部分。因为中值比最后的值还大说明没有减到最小值再开始后一部分的递增 - 若前两点不满足,
arr[mid]<arr[low]
那么最小值在左半部分。因为如果中值首元素还要小说明前半部分的递增已经结束,开始了后半部分的递增,而后半部分的每一个值都是要小于等于前半部分的每一个值的。
下边用Go来实现以上逻辑:
经验证可以输出正确的结果,关于时间复杂度,二分法的时间复杂度为O(logn),但是考虑到可能出现的最后一种情况就是数组中有大量重复的元素,出现了判定语句的最后一种情况需要遍历所有元素,故最坏情况下时间复杂度为O(n)