找出有序旋转数组里的最小值
假设将一个升序数组按照某个点进行旋转[0,1,2,3,4,5,6,7]
可能变成[4,5,6,7,0,1,2]
,然后找出旋转后的数组中的最小值,数组中不含重复数值。
1. 暴力法
可以知道除了没有旋转的情况下,最小的数位于数组中间,因此从后面往前搜索,如果找到了nums[end-1] > nums[end]
,那么nums[end]
就是最小的值。
public int findMin(int[] nums) {
int end = nums.length - 1;
while (end > 0) {
if (nums[end] < nums[end - 1]) {
return nums[end];
} else {
end--;
}
}
if (end == 0) {
return nums[0];
}
return -1;
}
2. 二分查找
public int findMin(int[] nums) {
int start = 0, end = nums.length - 1;
int mid;
// 数组只有1个数的情况 直接返回
if (nums.length == 1) {
return nums[0];
}
// 数组只有两个数的情况 返回两者中较小的值
if (nums.length == 2) {
return Math.min(nums[0], nums[1]);
}
// 数组的长度大于等于3
while (start < end) {
// 找出中间数
mid = (start + end) / 2;
// 如果nums[end]大于nums[mid] 说明nums[mid]处于前半段 继续往后搜索
if (nums[end] < nums[mid]) {
start = mid + 1;
} else {
// 否则说明已经搜索到了后半段
end = mid;
}
}
return nums[start];
}
3. 举例
输入:[4,5,6,7,0,1,2]
首先start = 0
、end = 6
第一轮: nums[start] = 4
,nums[end] = 2
,nums[mid] = 7
,所以start = mid + 1 = 4
第二轮: nums[start] = 0
,nums[end] = 2
,nums[mid] = 1
,所以end = mid = 5
第三轮: nums[start] = 0
,nums[end] = 1
,nums[mid] = nums[start] = 0
,所以end = mid = start
第四轮: 退出while循环