【题目】
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,给数组的最小值为1.
【分析】
直观讲,看到查找一个数组的最小值问题,第一感觉是利用直接顺序查找法,时间复杂度为O(N),这并没有什么优势在数组很大的情况下,观察数组发现它的部分是有序的,所以,我们想到用二分查找法来查找旋转数组的最小值,首先,要理解二分查找法的思想和顺序查找法的区别。
1.二分查找法思路:
对于给定的有序数组,查找关键字,采用对折的办法,先与中间的相比,由中间元素与关键字大小比较后决定关键字是在前半段还是后半段,这样每次比较都折一半,时间复杂度O(lgn)。
2.顺序查找法思路:
对于给定数组,无关有序无序,按顺序逐个比较寻找符合条件的关键字,时间复杂度O(N).
【流程设计】
对于本身是可以旋转成递增数组的变形数组来说,最普通的情况就是如同题目一样,将{1,2,3,4,5}变为{3,4,5,1,2},要找出最小值,采用二分查找法,设置两个指针,分别指向第一个元素和最后一个元素,第一个指针的元素如果大于第二指针的元素,说明数组是已排序好的,不用比较,第一个元素就是最小的,否则,现比较第一个指针和中间元素,如果中间元素大点,说明前面这半段数组是已排序,最小的应该出现在其后半段,将第一个指针指向中间元素,否则比较中间元素与最后一个指针,如果中间元素小了,说明后半段是已排序,那么最小的应该出现在中间元素的左边,也就是前半段数组中,将最后一个指针指向中间元素。
但是一旦出现像{1,1,1,0,1}这种,第一个等于最后一个等于中间的,所以只好用顺序查找法。
【测试代码】
#include<stdio.h>
#define ERROR 8888;
int Min(int *numbers, int length)
{
if(numbers == NULL || length <= 0)
{
return ERROR;//c语言没有抛出异常的包,所以这里就抛出设定数字。
}
int index1 = 0;
int index2 = length - 1;
int indexMid = index1;
while(numbers[index1] >= numbers[index2])
{
if(index2 - index1 == 1)
{
indexMid = index2;
break;
}
indexMid = (index1 +index2)/2;
if(numbers[index1] == numbers[index2] && numbers[index1] == numbers[indexMid])
{
int min = numbers[index1];
for(int i = 0 ; i< length; i++)
{
if(numbers[i]<min)
min = numbers[i];
}
return min;
}
if(numbers[indexMid] >= numbers[index1])
index1 = indexMid;
else if(numbers[indexMid] <= numbers[index2])
index2 = indexMid;
}
return numbers[indexMid];
}
int main()
{
int s1[] = {3,4,5,1,2};
int min1 = Min(s1,5);
printf("{3,4,5,1,2}最小值为:%d\n",min1);
int s2[] = {1,1,1,0,1};
int min2 = Min(s2,5);
printf("{1,1,1,0,1}最小值为:%d\n",min2);
int *p =NULL;
int min3= Min(p,5);
printf("{};最小值为:%d\n",min3);
return 0;
}
【测试结果】
原文地址:http://blog.csdn.net/xinyu913/article/details/46333665