题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
解题思路
概念:
递增排列:1,2,3,4,5,······
递减排列:9,8,7,6,5,······
非递减排列:1,2,3,5,5,7,8,······
非递增排列:8,7,7,6,4,3,1,······
思路一:暴力解法。直接遍历整个数组,找出最小值。
思路二:二分搜索法。(参考牛客网下的题解)
用中间值和高低位进行比较,看处于递增还是递减序列,进行操作缩小范围。
- 处于递增:low上移
- 处于递减:high下移(如果是high-1,则可能会错过最小值,因为找的就是最小值)
- 其余情况:low++缩小范围
其中要注意到一个特殊的情况:{0,1,1,1,1}的旋转数组{1,0,1,1,1} / {1,1,1,0,1}
代码实现
思路一:
public class Solution {
public int minNumberInRotateArray(int [] array) {
if(array.length == 0)
return 0;
int min = array[0];
for(int i = 1 ; i < array.length ; i ++)
if(array[i] < min)
min = array[i];
return min;
}
}
思路二:
public class Solution {
public int minNumberInRotateArray(int [] array) {
if (array.length == 0)
return 0;
int low = 0;
int high = array.length - 1;
int mid = 0;
while (low < high) {
if(array[low] < array[high])
return array[low];
// mid = (low + high) / 2;
mid = low + (high - low) / 2;
if (array[mid] > array[low]) // mid位于递增数组
low = mid + 1;
else if(array[mid] < array[high]) // mid位于递减数组
high = mid;
else
low ++;
}
return array[low];
}
}
后记
其实思路二看了好几遍题解,其中有坑的情况大佬们都处理得很巧妙,有时候画画示意图会比在脑中凭空想象使思路清晰得多,还是需要培养多多思维逻辑。
希望等过段时间回过头来二刷的时候,也可以写出这么漂亮的解答。