《剑指offer》面试题11:旋转数组的最小数字

更多剑指offer面试习题请点击: 《剑指offer》(第二版)题集目录索引

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


解题思路:
这题很明显是要利用旋转数组的特性,一个递增排序的数组旋转后可以把它分成两部分,这两部分又可以看作两个递增排序的数组,并且前面的子数组的元素一定会大于等于后面的子数组的元素。这里我们可以利用二分查找的思想。

用start和end表示首尾元素下标,mid表示中间元素下标。
①如果中间元素大于等于首元素,那么中间元素一定在前面那个子数组里面,那就意味着最小的元素一定在mid的后面,所以此时我们把 mid 赋值给start;

②如果中间元素小于等于尾元素,那么中间元素一定在后面那个子数组里面,那就意味着最小的元素一定在mid前面或者就是mid,此时就把mid赋值给end;

③如果start和end相邻了,那此时下标end所指向的元素就是最小元素。
这里写图片描述

注意: 这里一种特殊情况,数组{ 1, 0, 1, 1, 1 }的numbers[start] = numbers[mid] = numbers[end] = 1,此时程序判断numbers[mid] >= numbers[start] 成立,就会把mid赋值给start,最后程序返回的最终结果是1而不是0,所以如果程序遇到start、mid、end三个位置的值都相等情况下,只能采用顺序查找。


< code >

int Min(int* numbers, int length)
{
    if (NULL == numbers || length <= 0)
        return;

    int start = 0;
    int end = length - 1;
    int mid = start;

    //如果输入的数组是{1, 2, 3, 4, 5}那就直接返回numbers[start]。
    while (numbers[start] >= numbers[end])
    {
        if (end - start == 1) //此时最小的数就是numbers[end]
        {
            mid = end;
            break;
        }

        mid = start + ((end - start) >> 1);

        /*start、mid、end三个位置的数值相等,只能采用顺序查找*/
        if (numbers[start] == numbers[end]
            && numbers[mid] == numbers[start])
        {
            int ret = numbers[start];
            int i = start + 1;
            while (i <= end)
            {
                if (ret > numbers[i])
                {
                    ret = numbers[i];
                }
                i++;
            }
            return ret;
        }

        /*缩小范围*/
        if (numbers[mid] >= numbers[start])
            start = mid;

        else if (numbers[mid] <= numbers[end])
            end = mid;
    }

    return numbers[mid];
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值