旋转数组中的最小数字

来源:互联网 发布:联合国数据库怎么使用 编辑:程序博客网 时间:2024/05/08 06:08
  • 题目:把一个数组最开始的若干个元素搬到数组的末尾称之为数组的旋转,输入一个递增排序的数组的旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2},为数组{1,2,3,4,5}的一个旋转,该数组的最小值为1。
  • 思路解析:我们发现旋转之后的数组可以划分为两个排序的子数组。且前面子数组的元素都大于后面子数组的元素,并且最小的元素是两个数组的分界线,因此可以采用二分查找法进行查找。
  • 思路图解
    这里写图片描述

  • 算法分析:同二分法一样用两个指针分别指向第一个元素和最后一个元素,然后找到数组的中间元素如果中间元素大于等于第一个指针指向的元素说明中间元素在第一个数组里并且最小元素在中间元素的后面,我们需要把第一个指针往后移动到中间元素所在的位置,如果中间元素小于等于后一个指针所在位置的元素说明中间元素在第二个数组,中间元素可能是最小的,也可能最小元素在中间元素的前面,将后一个指针向前移动到中间元素的位置,继续执行上述的操作。直到两个指针距离相差为1,此时第一个指针指向第一个数组的最后一个元素,后一个指针指向第二个数组的第一个元素,此时最小的元素就是后一个指针所在位置的元素,循环终止返回最小元素。

  • 特殊情况考虑:
    这里写图片描述
    上述图片中的情况我们们的代码无法找到最小值的位置,因此需要特殊考虑,当遇到两个指针与中间位置的元素值相等时我们需要采用顺序查找。

  • 实现代码:

int Sort(int *arr,int start ,int end){    int result = arr[start];    int idx = start + 1;    while(idx < end)    {        if(arr[idx] < result)            result = arr[idx];        ++idx;    }    return result;}int Min(int *arr,int length){    assert(arr && length > 0);    int start = 0;    int end = length - 1;    int mid = start;    while(arr[start] >= arr[end])    {        if(1 == end - start)        {            mid = end;            break;        }        mid = (start + end) / 2;        if(arr[start] == arr[end] && arr[end] == arr[mid])            return Sort(arr,start,end);        if(arr[mid] >= arr[start])            start = mid;        else if(arr[mid] <= arr[end])            end = mid;    }return arr[mid];}
  • 完整代码请戳:
    https://coding.net/u/Hyacinth_Dy/p/MyCode/git/blob/master/%E9%9D%A2%E8%AF%95%E9%A2%986-%E6%97%8B%E8%BD%AC%E6%95%B0%E5%AD%97%E4%B8%AD%E7%9A%84%E6%9C%80%E5%B0%8F%E6%95%B0%E5%AD%97
0 0