题目:输入一个递增排序的数组的一个旋转,输出旋转数组的最小值。例如:数组{4,5,6,1,2,3}为数组{1,2,3,4,5,6}的一个 旋转数组,该数组的最小值为1。
思路:时间复杂度为O(n)的解法很简单。更高效的一种解法是利用二分查找实现O(lgn)的查找。两个标志begin和end,分别指向数组的第一个和最后一个元素。min指向数组中间项。如果arr[min]大于arr[begin],最小值在min的右边,是begin=min。如果arr[min]小于arr[begin],最小值在min的左边,是end=min。当end-begin=1时,最小值就是arr[end]。
有两种特殊情况:1、传入的数组是有序数组{1,2,3,4,5,6}
即:arr[begin] < arr[end],此时第一个数即为最小值。
2、数组{1,0,1,1,1}或{1,1,1,0,1},arr[begin]=arr[min]=arr[end],此时只能遍历数组,找出最小值。
#include<iostream>
using namespace std;
int LoopSearch(int *arr, int begin, int end);
int FindMin(int *arr, int len)
{
if (arr == NULL || len < 1)
return -1;
int begin = 0, end = len - 1;
//没有旋转的有序数组
if (arr[begin] < arr[end])
return arr[begin];
while (begin < end)
{
int mid = begin + (end - begin) / 2; //防止溢出
//最小值在右边
if (arr[mid] > arr[begin])
begin = mid;
//最小值在左边
else if (arr[mid] < arr[begin])
{
end = mid;
}
if (arr[begin] == arr[end] && arr[mid] == arr[end])
{
return LoopSearch(arr, begin, end);
}
if (end - begin == 1)
return arr[end];
}
}
int LoopSearch(int *arr, int begin, int end)
{
int min = arr[begin];
for (int i = begin + 1; i <= end; i++)
{
if (arr[i] < min)
min = arr[i];
}
return min;
}
int main()
{
int arr[] = { 4, 5, 6, 1, 2, 3 };
int len = sizeof(arr) / sizeof(arr[0]);
int min = FindMin(arr, len);
cout << "最小值: " << min << endl;
getchar();
return 0;
}