【剑指offer】面试题8----旋转数组的最小数字

1、题目

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。

例如数组{8,9,1,2,3,4,5,6,7}是{1,2,3,4,5,6,7,8,9}的一个旋转,该数组的最小值为1。


2、解题思路:

首先根据题目的要求来看,旋转后的该数组可以看成两部分,两个部分各自有序,且前面一部分的值始终大于后面部分的值,该数组的最小值就为后一部分的第一个元素。

设置两个标记,一个标记指向数组起始位置-first,一个标记指向数组末尾位置=last。

接着找到数组的中间位置,如果中间位置的值大于first,就令first=mid;否则令last=mid;直到结束循环条件为止。

这里写图片描述


3、源码


/*

旋转数组的最小数字

*/
#include<stdio.h>
#include<iostream>
using namespace std;

int MinInOrder(int arr[], int left, int right){
    int min = arr[left];
    for (size_t i = left + 1; i <= right; ++i){
        if (arr[i] < min)
            min = arr[i];
    }
    return min;
}

int Min(int arr[], int len){
    if (NULL == arr || len <= 0){
        throw new exception("Invalid parameters");
    }
    int first = 0;
    int last = len - 1;
    int mid = first;
    while (arr[first] >= arr[last]){
        if (last - first == 1){
            //此时两个标记相邻,说明最小的元素就是两个相邻元素靠后的那一个
            mid = last;
            break;
        }
        mid = (first + last) / 2;

        /*
            特殊情况:
            如果下标first,last,mid所指向的元素相等
            则此时应采取顺序查找的方法
        */
        if (arr[first] == arr[last] && arr[first] == arr[mid])
            return MinInOrder(arr, first, last);


        if (arr[mid] >= arr[first])
            first=mid;
        if (arr[mid] <= arr[last])
            last = mid;
    }
    return arr[mid];
}

void Print(int arr[], int len){
    for (size_t i = 0; i < len; i++){
        cout << arr[i] << " ";
    }
    cout << endl;
}

int main(){
    int arr[] = { 8, 9, 1, 2, 3, 4, 5, 6, 7 };

    int len = sizeof(arr) / sizeof(arr[0]);
    Print(arr, len);
    int ret = Min(arr, len);
    cout << "该数组最小的元素为:" << ret << endl;
}

4、结果

这里写图片描述

猜你喜欢

转载自blog.csdn.net/sofia_m/article/details/81322630