题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
解析
1. 递增数组的旋转,例如,数组{1 2 3 4 5},经过旋转可以是{2 3 4 5 1},{3 4 5 1 2},{1 2 3 4 5},{5 1 2 3 4},{4 5 1 2 3}。
2. 特例!这其中的数字可以重复,数组{0 1 1 1 1}可以旋转为{1 0 1 1 1},{1 1 1 0 1}等等。
3. 在可以可以缩小数组大小的时候,采用二分法查找。当遇到无法进行二分法缩小范围的时候,改用顺序查找法。
主要代码实现
int Min(int* number, int length){
if(number == NULL || length <= 0){
printf("输入有误!");
return -1;
}
int startIndex = 0;
int endIndex = length-1;
int midIndex = startIndex;
while(number[startIndex] >= number[endIndex]){
// 如果startIndex和endIndex指向相邻的两个数,
// 则startIndex指向第一个递增子数组的最后一个数字,
// endIndex指向第二个子数组的第一个数字,也就是数组中的最小数字
if(endIndex - startIndex == 1){
midIndex = endIndex;
break;
}
midIndex = (startIndex + endIndex) / 2;
//数组的收尾元素、中间元素大小相等,无法决定使用二分法
if(number[startIndex] == number[endIndex] && number[startIndex] == number[midIndex]){
return orderSearch(number, startIndex, endIndex);
}
//缩小查找范围
if(number[startIndex] <= number[midIndex]){
startIndex = midIndex;
}
else{
endIndex = midIndex;
}
}
return number[midIndex];
}
int orderSearch(int* number, int startIndex, int endIndex){
int result = number[startIndex];
for(int i=startIndex+1; i<=endIndex; i++){
if(result > number[i]){
result = number[i];
}
}
return result;
}
测试用例
采用《剑指offer》提供的源码中的测试用例
/ ====================测试代码====================
void Test(int* numbers, int length, int expected)
{
int result = 0;
result = Min(numbers, length);
for(int i = 0; i < length; ++i)
printf("%d ", numbers[i]);
if(result == expected)
printf("\tpassed\n");
else
printf("\tfailed\n");
}
int main(void){
// 典型输入,单调升序的数组的一个旋转
int array1[] = {3, 4, 5, 1, 2};
Test(array1, sizeof(array1) / sizeof(int), 1);
// 有重复数字,并且重复的数字刚好的最小的数字
int array2[] = {3, 4, 5, 1, 1, 2};
Test(array2, sizeof(array2) / sizeof(int), 1);
// 有重复数字,但重复的数字不是第一个数字和最后一个数字
int array3[] = {3, 4, 5, 1, 2, 2};
Test(array3, sizeof(array3) / sizeof(int), 1);
// 有重复的数字,并且重复的数字刚好是第一个数字和最后一个数字
int array4[] = {1, 0, 1, 1, 1};
Test(array4, sizeof(array4) / sizeof(int), 0);
// 单调升序数组,旋转0个元素,也就是单调升序数组本身
int array5[] = {1, 2, 3, 4, 5};
Test(array5, sizeof(array5) / sizeof(int), 1);
// 数组中只有一个数字
int array6[] = {2};
Test(array6, sizeof(array6) / sizeof(int), 2);
// 输入NULL
Test(NULL, 0, 0);
system("pause");
return 0;
}