旋转数组的最小数字

来源:互联网 发布:淘宝不能结算怎么回事 编辑:程序博客网 时间:2024/06/10 13:41

题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小元素为1。

我们可以想到,这个旋转后的数组可以以看成两段有序区间。如上述题目中, 3,4,5是第一个递增区间,后面的1,2是第二个递增区间。并且,这个最小的数一定是两个递增区间的分界线。基于这些分析,我们就可以用二分法在log(N)的时间内找到旋转数组的最小数。
我们可以定义左右指针以及中间元素的指针。让第一个指针总是指向第一个递增数组的元素,第二个指针总是指向第二个递增数组的元素。
比如:我们给一个数组{1,2,3,4,5,6,7}。它的旋转数组是{6,7,1,2,3,4,5}。
分析过程如下:
这里写图片描述
基于以上分析,我们给出如下代码:

int MinArr(int* a, int length){    if (a == NULL || length < 0)        return -1;    int index1 = 0;    int index2 = length - 1;    int Mid = index1;    while (a[index1] >= a[index2])    {        if (index2 - index1 == 1)        {            Mid = index2;            break;        }        Mid = (index1)+index2 / 2;        if (a[Mid] >= a[index1])//说明Mid在第一个递增区间            index1 = Mid;        else if (a[Mid] <= a[index2])//说明Mid在第二个递增区间            index2 = Mid;    }    return a[Mid];}int main(){    int a[] = { 1,1,1,0,1};    int sz = sizeof(a) / sizeof(a[0]);    int ret = MinArr(a, sz);    cout << ret << endl;    system("pause");    return 0;}

上面的程序看起来似乎是解决了问题,但我们还没有考虑到特殊情况,比如当数组是{0,1,1,1,1,1}时,给出旋转数组{1,0,1,1,1,1},那么此时,按照上面的程序,a[index1]=a[Mid]=a[index],程序返回结果并不是我们想要的。
这种情况就需要特殊处理,只能从前到后依次遍历数组。

#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>using namespace std;int MinInOrder(int* a, int index1, int index2){    int ret = a[index1];    for (size_t i = index1 + 1; i < index2; i++)    {        if (ret > a[i])            ret = a[i];    }    return ret;}int MinArr(int* a, int length){    if (a == NULL || length < 0)        return -1;    int index1 = 0;    int index2 = length - 1;    int Mid = index1;    while (a[index1] >= a[index2])    {        if (index2 - index1 == 1)        {            Mid = index2;            break;        }        Mid = (index1)+index2 / 2;        if (a[index1] == a[Mid] && a[Mid] == a[index2])            return MinInOrder(a, index1, index2);        if (a[Mid] >= a[index1])//说明Mid在第一个递增区间            index1 = Mid;        else if (a[Mid] <= a[index2])//说明Mid在第二个递增区间            index2 = Mid;    }    return a[Mid];}int main(){    int a[] = {1,0,1,1,1,1};    int sz = sizeof(a) / sizeof(a[0]);    int ret = MinArr(a, sz);    cout << ret << endl;    system("pause");    return 0;}

这里写图片描述

原创粉丝点击