O(n)和使用Arrays.sort(nums)的方法就不再写了。真是各种花式使用二分搜索啊...二分搜索的关键点在与left,right指针移动条件的判定,这道题目的判定条件非常巧妙。使用nums[mid]和nums[n - 1]进行比较,如果nums[mid]比较大的话,那么说明mid这个元素必然在rotated part里面,而最小的元素必然是rotated part后面的一个元素,所以left = mid + 1;而如果nums[mid]比较小的话,说明mid这个元素在右侧的rotated part里面,并不一定是头部,所以应该将right = mid - 1。最终当最后一步left == right的时候,必然有nums[left]为数组中的最大值或最小值,如果是最大值,那么left++,如果是最小值的话,right--,最终nums[left]得到的都是最小值。时间复杂度为O(logn),代码如下:
public class Solution {
public int findMin(int[] nums) {
if(nums == null || nums.length == 0){
return 0;
}
int left = 0;
int right = nums.length - 1;
while(left <= right){
int mid = (left + right) / 2;
if(nums[mid] > nums[nums.length - 1]){
left = mid + 1;
}else{
right = mid - 1;
}
}
return nums[left];
}
}
知识点:
1. 二分搜索不仅仅可以用于在完全排序的数组中找某个固定的数字,也可以在rotated sorted array中使用,看到题目中的这点要有使用二分搜索的敏感度,这时候需要注意的问题就是判定left与right移动的条件
2. 锻炼从二分搜索中判定left与right移动的条件来推断最终left与right指针的位置,比如说这道题目,因为条件判断是nums[mid]与nums[n - 1]的大小比较,所以整体的趋势是想数组rotated结点移动的,故而当left == right的时候,可能停在的位置是最大值或者最小值,但是又由于很对最大值和最小值两种情况下left指针的变化,所以最后return nums[left]即可