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;
}