---
主题列表:juejin, github, smartblue, cyanosis, channing-cyan, fancy, hydrogen, condensed-night-purple, greenwillow, v-green, vue-pro, healer-readable, mk-cute, jzman, geek-black
贡献主题:github.com/xitu/juejin…
theme: juejin highlight:
题目
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。
示例 1:
输入:[3,4,5,1,2] 输出:1 示例 2:
输入:[2,2,2,0,1] 输出:0
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/xu…
思路
-
暴力破解:从头遍历一遍数组,比较当前元素 curr 和下一个元素next的大小,当 curr > next 时 next 元素就是数组最小值。
- 边界条件:原数组所有元素相同,这时遍历到最后一个元素也找不到比 curr 小的next元素,但此时数组任意一个元素都可以作为最小值。
-
二分查找:原数组是递增排序的数组,旋转后的数组可以看做两个递增排序的子数组。而要求解的数组最小值就是两子数组的交界点。定义 left = 0, right = len - 1, mid = left + (right-left) / 2;
-
当 mid = (left + (right-left)/2 ) > right 时表示 mid 在第一段数组,此时mid左侧元素整体升序,交界点在 mid 右侧。所以 left = mid + 1。
4 5 6 1 2 mid = 6 right = 2 -
当 mid = (left + (right-left)/2) < right 时表示 mid 在第二段数组,此时mid右侧元素整体升序,交界点在 mid 左侧或 mid 就是交界点。right = mid
6 1 2 4 5 mid = 2 right = 5 -
当 mid = right 时不能判定交界点是在 mid 左侧还是右侧,暴力移动右指针 right--。
3 1 3 3 3 mid = 3 left = right = 3 3 3 3 1 3 mid = 3 left = right = 3
-
代码实现
public int minArray(int[] numbers) {
if (numbers.length == 0) return 0;
int len = numbers.length;
int left = 0, right = len-1;
while (left < right) {
int mid = left + (right - left) / 2;
if (numbers[mid] > numbers[right]) {
left = mid + 1;
} else if (numbers[mid] < numbers[right]) {
right = mid;
} else {
right--;
}
}
return numbers[left];
}