欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-06-17 19:46:22
...

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;直到结束循环条件为止。

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


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、结果

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