把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。请返回旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一次旋转,该数组的最小值为1。
这道题(冷笑)居然考二分,直接遍历输出也能过……
考虑二分的方法:
5 6 7 8 1 2 2
下标low = 0,high = size-1,
对于中间值8大于“最后”一个值时,要舍弃左区间,此时mid值也舍掉,因为它又不可能是最小的值,low置为mid+1;
对于中间值2等于“最后”一个值时,我们无法判断前还是后存在最小值,所以我们将high- -;
(这里对相等情况附加一句,因为二刷的时候这道题又不会了,QAQ当mid与右边界值相等时,我们可以肯定这不是最小值,所以可以舍掉右边界值high–)
对于中间值已经小于最后一个值时,要舍弃右区间,但是对于当前mid值,有可能成为最小值,high置为mid。
循环比较,直到low >= high为止结束。
当前low指向的值即为最小值。
int minArray(int* numbers, int numbersSize){ //生活太累了,我可以邀请你去云朵☁️上打呼噜吗 // int min_num = numbers[0]; int low = 0; int high = numbersSize-1; int mid = (low + high)/2; while(low < high) { if(numbers[mid] > numbers[high]) { low = mid+1; } else if(numbers[mid] < numbers[high]) { high = mid; } else { high--; } mid = (low+high)/2; } return numbers[low]; }
在最坏情况下,如果数组中的元素完全相同,退化成遍历,那么while 循环就需要执行n 次,每次忽略区间的右端点,时间复杂度为O(n)。