旋转数组的最小数字
题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
题解
思路1
直接遍历
时间复杂度: O(N)- 空间复杂度: O(1)
思路2
二分查找
分析:旋转数组可以看成是两个有序数组组成的,最小元素就是这两个数组的分界点
用两个指针进行二分查找,lo指针总是指向第一个数组的终点,hi指针总是指向第二个数组的起点
直到 lo 与 hi相邻,即 lo == hi -1
时间复杂度: O(log (N))- 空间复杂度: O(1)
public int minNumberInRotateArray(int[] array) {
if (array.length == 0)
return 0;
int lo = 0;
int hi = array.length - 1;
int m = (lo + hi) / 2;
while (lo != hi - 1) {
if (array[lo] <= array[m]) {
lo = m;
m = (lo + hi) / 2;
}
if (array[hi] >= array[m]) {
hi = m;
m = (lo + hi) / 2;
}
}
return array[hi];
}等等
这样写有缺陷
比如 {1,0,1,1,1} 和 {1,1,1,0,1} 这两个
如果中间指针 和 前后指针都相等的情况,找不出最小的
碰到这种情况只能顺序查找了
public int minNumberInRotateArray(int[] array) {
if (array.length == 0)
return 0;
int lo = 0;
int hi = array.length - 1;
int m = (lo + hi) / 2;
while (lo < hi - 1) {
/*这种特殊情况,只能顺序查找*/
if (array[lo] == array[hi] && array[lo] == array[m]) {
int res = 0;
for (int i = lo + 1; i < hi; i++) {
if (res > array[i])
res = array[i];
}
return res;
}
if (array[lo] <= array[m]) {
lo = m;
m = (lo + hi) / 2;
}
if (array[hi] >= array[m]) {
hi = m;
m = (lo + hi) / 2;
}
}
return array[hi];
}
查看24道真题和解析