剑指Offer11.旋转数组的最小数字
1.暴力法:
我们可以直接遍历这个数组,显然这个方法的时间复杂度是O(n)。我们看到旋转数组的特点就是,可以划分为两个排序好的数组,最小的元素正是这两个数组的分界线,因此我们可以不用完全遍历完这个数组。
class Solution {
public int minArray(int[] numbers) {
int min = numbers[0];
for (int i = 1; i < numbers.length; i++) {
if (numbers[i] < min)
return numbers[i];
}
return min;
}
}
2.二分法:
由上述可知,该数组能分为两个数组。
同二分法设置三个指针,一个指向数组头left,一个指向数组尾right,一个指向数组中间middle。
如果middle处的值大于right处的值,则说明middle处在第一个数组,最小值是在middle的右边。
如果middle处的值小于right处的值,则说明middle处在第二个数组,最小值是在middle处的左边或者是自己本身。
如果middle处的值等于right处的值,,由于重复元素的存在,我们并不能确定middle是在最小值的左侧还是右侧,因为middle的值替代了此时right处的值,所以我们可以忽略右端点,让其左移一位。
class Solution {
public int minArray(int[] numbers) {
int left = 0;//左指针
int right = numbers.length - 1;//右指针
int middle = left;//中间指针
while(left < right) {
middle = (left + right) / 2;
if (numbers[middle] > numbers[right])
left = middle + 1;
else if (numbers[middle] < numbers[right])
right = middle;
else
right--;
}
return numbers[right];
}
}