链接
https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof/
难度: #简单
题目
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。请返回旋转数组的最小元素。例如,数组 [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
注意:本题与主站 154 题相同:https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array-ii/
代码框架
class Solution {
public int minArray(int[] numbers) {
}
}
题目解析
解答思路1:
暴力解法,
查看数组的每一个元素和前一个元素的关系,
如果比前一个小,
则确定是最小的元素。
解答思路2:
观察发现,可以使用二分思想,
将数组从最小值的地方分成左右两部分,
左边数组是递增序列,
右边数组也是递增序列,
使用二分思想进行查找,
找到中间值和最右边的元素比较,
如果中间值小于最右边元素,
说明右半边有序,则最小值出现在左半边部分,
如果中间值大于最右侧元素,
说明最小值出现在右半边部分,
因为存在最小值,打破了递增序列,
需要利用二分思想进一步在可能的半边查找。
如果中间值等于最右侧元素,
说明存在重复的元素,无法进一步判断最小值的范围,
可以去掉重复元素,缩小查找范围。
测试用例
package edu.yuwen.sowrd.num11.solution;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import edu.yuwen.sowrd.num11.sol2.Solution;
public class SolutionTest {
/**
* 输入:[3,4,5,1,2]
* 输出:1
*/
@Test
public void testCase1() {
Solution solution = new Solution();
int[] numbers = { 3, 4, 5, 1, 2 };
int min = solution.minArray(numbers);
Assertions.assertEquals(1, min);
}
/**
* 输入:[2,2,2,0,1]
* 输出:0
*/
@Test
public void testCase2() {
Solution solution = new Solution();
int[] numbers = { 2, 2, 2, 0, 1 };
int min = solution.minArray(numbers);
Assertions.assertEquals(0, min);
}
/**
* 输入:[3,1,3,3]
* 输出:1
*/
@Test
public void testCase3() {
Solution solution = new Solution();
int[] numbers = { 3, 1, 3, 3 };
int min = solution.minArray(numbers);
Assertions.assertEquals(1, min);
}
}
解答1
package edu.yuwen.sowrd.num11.sol1;
public class Solution {
public int minArray(int[] numbers) {
for (int i = 1; i < numbers.length; i++) {
if (numbers[i - 1] > numbers[i]) {
return numbers[i];
}
}
// 找不到比第一个元素小的,则第一个元素是最小值
return numbers[0];
}
}
解答2 推荐
package edu.yuwen.sowrd.num11.sol2;
public class Solution {
public int minArray(int[] numbers) {
int low = 0;
int high = numbers.length - 1;
// 注意这里的退出条件
while (low < high) {
int mid = low + (high - low) / 2;
int mNum = numbers[mid];
int rNum = numbers[high];
// 是递增序列,则查找左半边部分
if (mNum < rNum) {
high = mid;
}
// 不是递增序列,则查找右半边部分
else if (mNum > rNum) {
low = mid + 1;
}
// 如果存在重复元素则排除掉,再重新查找
else {
high--;
}
}
return numbers[low];
}
}