面试题-旋转数组的最小数字

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

直接反应出来的是把所有数遍历一边,找出最小的数。但本题一定有特殊性,因为分成了两个递增的子数组。那么,为何不利用头尾指针采取两头往中间的临界值遍历,这种方法大大降低了时间复杂度。这种方法类似二分法。

#include <iostream>

using namespace std;

int MyMin(int a[],int len)
{
    int Head = 0, Tail = len-1,Middle = Head;//头尾遍历数组的下标 先把中间元素下标置0 


    // 同样,中间元素 小于 尾元素,那么 中间元素 在 右数组中,即目标最小的数还在中间元素的前面
    while(a[Head]>=a[Tail])// 当首指针指向的元素 大于 尾指针指向的元素时,如果 首位指针挨在一起,那么尾指针所指向的一定是最小元素
    {
        if(Tail-Head==1)
        {
            Middle = Tail ;
            break;
        }
    // 当 头尾指针 不相邻时,取中间指针,并将 中间指针 所指向的元素 与 头指针 和 尾指针 指向的元素的 比较大小
        Middle = (Head+Tail)/2;
    // 如果 中间元素 大于 头元素,那么 中间元素 还在 左数组中,即目标最小的数还在右数组中,需要逐渐缩小 范围,于是 就将头指针 指向中间元素
        if(a[Middle]>=a[Head])
            Head = Middle;
    // 同样,中间元素 小于 尾元素,那么 中间元素 在 右数组中,即目标最小的数还在中间元素的前面
        else if(a[Middle]<=a[Tail])
            Tail = Middle;
    }
    return Middle;//返回最小值下标 

}

int main()
{
    //定义一个旋转数组 
    int a[] = { 4, 5, 6, 7, 0, 1, 2, 3 };
    int length = sizeof(a) / sizeof(a[0]);

    int min = MyMin(a, length);

    cout << "Min:" << a[min] << endl;

    return 0;
} 

这里写图片描述

与此同时,我们会忽略程序的特殊性。如果一个数组1, 0,1,1,1 旋转之后1,1,1,0,1。这个时候头和尾指向的元素一样,你还能用中间元素去判别吗?显然不行。遇到这种情况下,只能顺序遍历了。

#include <iostream>

using namespace std;

int MinOrder(int a[],int Head,int Tail)
{
    int result = a[Head];
    for (int i = Head + 1; i <= Tail; i++)
    {
        if (a[i] < result)
            result = a[i];
    }
    return result;
}

int MyMin(int a[], int len)
{
    int Head = 0, Tail = len - 1, Middle = Head;

    while (a[Head] >= a[Tail])
    {
        if (Tail - Head == 1)
        {
            Middle = Tail;
            break;
        }

        Middle = (Head + Tail) / 2;

        //判断分类操作 当出现 数组首元素 和 尾元素 都等于 中间元素时,调用另一个函数
        if (a[Middle] == a[Head] && a[Head] == a[Tail])
            return MinOrder(a, Head, Tail);

        if (a[Middle] >= a[Head])
            Head = Middle;
        else if (a[Middle] <= a[Tail])
            Tail = Middle;
    }
    return a[Middle];
}

int main()
{
    // 定义一个旋转数组
    int a[] = { 1, 1, 1, 1, 0, 1 };
    int length = sizeof(a) / sizeof(a[0]);

    int min = MyMin(a, length);

    cout << "Min:" << min << endl;

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值