把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。
示例 1:
1 | 输入:[3,4,5,1,2] |
示例 2:
1 | 输入:[2,2,2,0,1] |
1.一次失败的尝试
这题思路很简单, 就是求出mid之后然后和两端元素比较, 判断最小值在mid左边还是右边.
重点是处理重复的元素. 如果numbers[mid] == numbers[begin]或numbers[end]会怎样.
我一开始是同时用了三个元素来判断, numbers[mid], numbers[begin], numbers[end]
如果
numbers[begin] == numbers[mid], 就将begin右移直到不等于numbers[mid]如果
numbers[end] == numbers[mid], 就将end左移直到不等于numbers[mid]如果
numbers[mid] > numbers[begin]就说明最小值在mid到end中如果
numbers[mid] < numbers[end]就说明最小值在begin到mid中.
后来发现这三个元素是不必要的. 只需要判断numbers[mid], numbers[end]即可. 因为比numbers[end]大并且比numbers[begin]小的元素是不存在的. 只要比numbers[end]大就可以说明最小值在mid到end中了.
而且, 如果碰到了numbers[end] == numbers[mid]的情况, 只需要end左移一次就好, 下一次迭代重新计算mid和end就好, 不用一直移动end直到numbers[end] != numbers[mid]. 时间上不会有任何提升而且会使得逻辑错误.
1 | //失败代码, 最后被numbers[mid] == numbers[end]和numbers[mid] == numbers[begin]这种情况搞得一团糟 |
2. 正确解法
只需要判断numbers[mid], numbers[end]即可. 因为比numbers[end]大并且比numbers[begin]小的元素是不存在的. 只要比numbers[end]大就可以说明最小值在mid到end中了.
而且, 如果碰到了numbers[end] == numbers[mid]的情况, 只需要end左移一次就好, 下一次迭代重新计算mid和end就好, 不用一直移动end直到numbers[end] != numbers[mid]. 时间上不会有任何提升而且会使得逻辑错误.
1 | class Solution { |