1.题目描述:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
2. 相关知识:
查找和排序是是面试考察算法的重点,我们应该重点掌握二分查找、归并排序和快速排序,做到能随时正确、完整地写出它们的代码。
- 查找算法:顺序查找、二分查找、哈希查找、二叉排序树查找。
- 排序算法:插入排序、冒泡排序、归并排序、快速排序,面试者一定要能写出完整的代码,并对各种排序算法的特点烂熟于胸,能够从空间消耗、平均时间复杂度和最差时间复杂度等方面比较它们的优缺点。
查找算法性能分析:为确定记录在查找表中的位置,需和给定值进行比较的关键字个数的期望称为查找算法在查找成功时的用平均查找长度(Average Search Length, ASL)。
设
n
为记录数,
顺序查找的平均查找长度
等概率条件下
Pi=1/n
,
ASL=(n+1)/2
。所以,顺序查找的算法复杂度为
O(n)
。
折半查找可用判定树进行分析,二叉树长度
n
与深度
推导过程第四、六行均使用了等比数列求和公式,倒数第二行将 h=log2(n+1) 代入其中。当 n 较大时,
二叉排序树:左子树小于根结点,右子树大于根结点。查找过程中动态生成树的结构,因而其平均查找长度和树的形态有关。最坏情况是插入的关键字有序时,构成的二叉排序树退化为单支树,其平均查找长度为
(n+1)/2
,与顺序查找相同;最好的情况是构成二叉树形态与折半查找判定树相同,平均查找长度与
log2(n)
成正比。
为了使得二叉排序树的性能不退化为单支树,需要对树进行平衡化处理。平衡二叉树的所有左右子树的深度差的绝对值不超过1。平衡二叉树的构建需要对树进行“旋转”处理。
3. 解答思路:
采用类似于二分法查找的算法,并且考虑特殊情况
4. 代码实现:
#include "stdafx.h"
int minInOrder(int* numbers, int index1, int index2)
{
int result = numbers[index1];
for (int i=index1;i<=index2; i++)
{
if (numbers[i]<result)
result = numbers[i];
}
return result;
}
int getMin(int* numbers, int length)
{
if(numbers == NULL || length <= 0)
printf("error");
int index1 = 0;
int index2 = length - 1;
int mid = index1;
while(numbers[index1] >= numbers[index2])
{
if(index2 - index1 == 1)
{
mid = index2;
break;
}
mid = (index1 + index2) / 2;
if (numbers[index1] == numbers[index2] && numbers[mid] == numbers[index2])
{
return minInOrder(numbers, index1, index2);
}
if(numbers[mid] >= numbers[index1])
index1 = mid;
else if(numbers[mid] <= numbers[index2])
index2 = mid;
}
return numbers[mid];
}
int _tmain(int argc, _TCHAR* argv[])
{
//int testData[5] = {3, 4, 5, 1, 2};
int testData[5] = {1, 0, 1, 1, 1};
int min = getMin(testData, 5);
printf("min is %d\n", min);
return 0;
}