比暴力遍历好一丢丢的解法
旋转数组的最小数字
http://www.nowcoder.com/questionTerminal/9f3231a991af4f55b95579b44b7a01ba
这里提供一个比暴力遍历好一丢丢的解法(最优解还是看官方题解吧,我这个算是暴力解法的小优化版)。
假设一个非递减数组:1 2 3 4 5 6:
它有一个旋转是:3 4 5 6 1 2,可以视为两个非递减序列3 4 5 6和1 2 的组合;
它有一个旋转是:5 6 1 2 3 4,可以视为两个非递减序列5 6和1 2 3 4的组合;
它有一个旋转是:6 1 2 3 4 5,可以视为两个非递减序列6和1 2 3 4 5的组合……
观察规律,我们就有遍历的头猪(xu)了,在数组最小值1的前面,是一个非递减序列。
假设输入一个非递减数组的旋转数组a[0..n],可以设计出以下的遍历逻辑:
for(int i=0; i<=n-1;i++){
if(a[i]<=a[i+1]) {} //如果数组下标从0到i+1可以维持非递减序列,继续遍历(实际代码里这句可以省略)
else /等价于if(a[i]>a[i+1])/ return a[i+1]; //数组下标从0到i+1不再是非递减序列,即a[i]到a[i+1]数值大小是向下跳变的,a[i+1]就是数组最小值,return a[i+1]
}
return a[0]; //没能在for循环里返回,说明a是一个非递减序列,a[0]就是最小的元素,返回a[0]
时间复杂度:O(n),实际用起来会比O(n)小,因为发现了数值大小跳变的地方就返回了。
示例:假设一个非递减数组:1 2 3 4 5 6,n=6;
它有一个旋转是:3 4 5 6 1 2(旋转4次),遍历4次找到结果;
它有一个旋转是:6 1 2 3 4 5(旋转1次),遍历1次找到结果;
直接把1 2 3 4 5 6输进去(旋转0次),不能在for循环中找到结果,说明是一个非递减序列,返回a[0]最小值。遍历了6次。
也就是说一般情况下,一个有序数组被旋转了c次,就要遍历c%n次找到结果(特殊情况c%n==0,要把数组遍历完)。
public int minNumberInRotateArray(int[] rotateArray) { // write code here if(rotateArray.Length==0) return 0; for(int i=0; i<rotateArray.Length-1; i++){ if(rotateArray[i]>rotateArray[i+1]) return rotateArray[i+1]; } return rotateArray[0]; }