原始题目:剑指 Offer 11. 旋转数组的最小数字 (opens new window)
# 方法一:二分查找
题目给的数组是有序数组,可以考虑使用二分查找,可以将遍历法的线性级别转化为对数级别。
假定数组的左边位置是 ,右边是 , 和 的中心位置为 。
若 , 说明 区间是递增的,那么最小值应该出现在 区间。
若 , 说明 区间是先递增后递减的,那么最小值应该现在 区间。 不会是最小值。
若 , 则无法判断 区间的单调性,但是可以把 去掉。因为即使去掉 ,数组中还有 ,所以不会对结果产生影响,把区间缩减为 。
补充说明:
上面的思路中,一直都是 和 的对比,那么能不能将 和 对比呢?
举例: 与 ,此时,中间位置的值都比左边大,但最小值一个在后面,一个在前面,因此这种做法不能有效地减治。
代码:
public int minArray(int[] nums) {
if (nums == null || nums.length == 0) {
return -1;
}
int l = 0;
int r = nums.length - 1;
while (l < r) {
int mid = l + ((r - l) >> 1);
if(nums[mid] < nums[r]){
r = mid;
} else if (nums[mid] > nums[r]){
l = mid+1;
} else {
// 舍弃 nums[r]
r--;
}
}
return nums[r];
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
复杂度分析
时间复杂度: 在特例情况下(例如 ),会退化到 。
**空间复杂度 **: 使用的都是常数大小的空间。