概念:
旋转数组就是,将一个排序数组的前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; }
注意:
扫描二维码关注公众号,回复:
1740172 查看本文章
需要考虑到一种情况,当第一个元素等于中间元素并且等于最后一个元素,我们无法判断中间元素到底属于哪一个子数组,此时,就需要顺序查找。