旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组
[3,4,5,1,2]
为[1,2,3,4,5]
的一个旋转,该数组的最小值为1。示例 1:
输入:[3,4,5,1,2] 输出:1
题解
-
二分法
- 可能出现的情况
- 一般情况下,数组起始元素大于末尾元素
- 可能旋转了0个元素,即
[3,4,5,1,2]
旋转后的数组为[3,4,5,1,2]
- 可能出现起始,末尾,中间元素都是相同的情况,此时无法确定中间元素在第一个递增序列中还是在第二个递增序列中
- 我的写法
class Solution { public int minArray(int[] numbers) { int headIndex = 0, tailIndex = numbers.length - 1,middleIndex; if(numbers.length == 2){ return numbers[0] > numbers[1] ? numbers[1] : numbers[0]; } while(tailIndex-headIndex > 1){ if(numbers[headIndex] < numbers[tailIndex]){ return numbers[headIndex]; } middleIndex = (headIndex + tailIndex)/2; if(numbers[middleIndex] == numbers[headIndex] && numbers[middleIndex] == numbers[tailIndex]){ int low = numbers[0]; for(int i = 1; i < numbers.length - 1; i++){ if(numbers[i] < low){ low = numbers[i]; } } return low; }else if(numbers[middleIndex] >= numbers[headIndex]){ headIndex = middleIndex; }else{ tailIndex = middleIndex; } } return numbers[tailIndex]; } }
- 大神写法
class Solution { public int minArray(int[] numbers) { int i = 0, j = numbers.length - 1; while (i < j) { int m = (i + j) / 2; if (numbers[m] > numbers[j]) i = m + 1; else if (numbers[m] < numbers[j]) j = m; //当中间元素等于末尾元素的时候,则起始元素可能大于等于中间和末尾元素 else j--; } return numbers[i]; } }
- 时间复杂度:O(logn),特殊情况下:【1,1,1,1】会退化到O(n)
- 空间复杂度:O(1)
- 可能出现的情况
总结
要注意特殊情况,边界测试
此题的特俗情况有
1、旋转了0个元素
2、出现起始,末尾,中间元素相同的情况