把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转,输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,6,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1.
关于思路:
1.寻找一个数组中的最小的数字,可以直接遍历整个数组。
2.我们应该抓住两点,首先这个数组本来是递增的,那么我完成一次旋转以后,数组的内部可以看成是两个递增的数 组,那么最小的数字一定在最大的数字后面。可以设定边界值,利用二分查找来找到最小的元素。
3.对于一些递增不明显的是否可以处理,比如说{1,0,1,1,1}是数组{0,1,1,1,1}的旋转,此时在处理的时候,边界值和中间 值都一样,二分查找就不行了,就只能顺序遍历。
关于代码
依据上诉三条思路写出如下三个代码:
代码一:
int Findmin(int *a,int length)
{
if (a == NULL)
return 0;
int i = 0;
while (i<length)
{
if (a[i] < a[i + 1])
{
i++;
}
else
{
return a[i+1];
}
}
}
结果为:
代码二:
int Findmin(int*a, int length)
{
if (a == NULL || length <= 0)
printf("ERROR");
int index1 = 0;
int index2 = length - 1;
int middle = 0;
while (a[index1] >= a[index2])
{
if (index2 - index1 == 1)
{
middle = index2;
break;
}
middle = (index1 + index2) >> 1;
if (a[index1] <= a[middle])
{
index1 = middle;
}
else if (a[index2] >= a[middle])
index2 = middle;
}
return a[middle];
}
结果:
代码三:
int min(int *a,int index1,int index2)
{
int i = 0;
int ret = a[index1];
for (i=index1+1; i < index2; i++)
{
if (ret >a[i])
{
ret = a[i];
}
}
return ret;
}
int Findmin(int*a, int length)
{
if (a == NULL || length <= 0)
printf("ERROR");
int index1 = 0;
int index2 = length - 1;
int middle = 0;
while (a[index1] >= a[index2])
{
if (index2 - index1 == 1)
{
middle = index2;
break;
}
middle = (index1 + index2) >> 1;
if (a[index1] == a[middle] && a[middle] == a[index2])
{
return min(a,index1,index2);
}
if (a[index1] <= a[middle])
{
index1 = middle;
}
else if (a[index2] >= a[middle])
index2 = middle;
}
return a[middle];
}
结果:
关于总结:
代码一的代码只能解决一般问题不能解决之前提到的特殊问题,而且代码一的办法时间复杂度是O(N),代码二的代码也只能解决一般情况不能解决特殊情况,但是用了二分查找的思想,降低了时间复杂度,代码三的代码不仅能解决一般情况还能解决特殊情况,所以本人觉得代码三的代码可用性更高。