概念:
旋转数组就是,将一个排序数组的前n位数挪到数组的后面,我们称之为旋转数组。例如数组{3,4,5,1,2}就是数组{1,2,3,4,5}的一个旋转。
分析:
找出一个数组中最小的数并不难,只需遍历数组即可,但是次方法的时间复杂度为O(n),而且没有利用旋转数组的特性。
解决:
我们注意到旋转后的数组实际上可划分为两个排序的数组,而且前面的子数组的值都要大于或等于后面的子数组的元素。并且最小的元素恰好是是这两个子数组的分界线。所以试着用二分查找法来寻找这个数。
使用两个指针分别指向数组的第一个数和最后一个数,接着求出中间元素,如果中间元素位与前面的递增子数列,那么他应该大于或者等于第一个指针指向的元素,此时将第一个指针指向中间元素,这样就缩小了查找范围,同样依照此原理,可以把end指针也指向中间元素,也可以缩小范围。
如果第一个指针和第二个指针相差为一时,end指针所指向的值就是最小值。
代码如下:
#include<iostream>
using namespace std;
int find_inorder(int *array, int len)
{
int min = array[0];
for (int i = 1; i < len; i++)
{
if (array[i] < min)
{
min = array[i];
}
}
return min;
}
int Find(int *array, int len)
{
int start = 0;
int end = len - 1;
int mid = start;
while (array[start] >= array[end])
{
if (end - start == 1)
{
mid = end;
break;
}
int mid = (start + end) / 2;
if (array[start] == array[mid] && array[start] == array[end])
{
return find_inorder(array,len);
}
if (array[mid] >= array[start])
{
start = mid;
}
if (array[mid] <= array[end])
{
end = mid;
}
}
return array[mid];
}
int main()
{
int array[] = {1,0,1,1,1 };
int len = sizeof(array) / sizeof(array[0]);
int min = Find(array, len);
cout << min << endl;
return 0;
}
注意:
需要考虑到一种情况,当第一个元素等于中间元素并且等于最后一个元素,我们无法判断中间元素到底属于哪一个子数组,此时,就需要顺序查找。