题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
分析:数组在旋转之前是有序的,旋转后的数组可以看成是两个有序序列,在这两个有序序列里面求最小值。我们可以通过二分查找的思想来实现本题。伪代码描述如下:
输入:数组arrSearch
输出:最小数
初始化:数组长度length,参数low=0,high=length-1,middle=low
1 if(arrSearch=null||arrSearch.length==0)
2 数组不能为空
3 end if
4 while(arrSearch[low]>=arrSearch[high])
5 if(low=high-1)
6 middle = high;
7 break;
8 end if
9 middle = (low+high)/2;
9 if(arrSearch[middle]>=arrSearch[low])
10 low = middle;
11 else if(arrSearch[middle]=<arrSearch[high])
12 high = middle;
13 end if
14 end while
15 return arrSearch[middle];
初始化时候让middle=low,假如旋转数组是升序,第一个数就是最小值,直接输出就可以。以上伪代码看似完美,但是没有考虑数组的特殊性,假如旋转数组是{1,1,1,0,1}这种情况,arrSearch[low],arrSearch[middle],arrSearch[high三个值是相等的,没办法判断中间数是这两个序列中的哪一个,这个时候只能使用顺序查找。
在9处添加顺序查找,顺序查找伪代码描述如下:
if(arrSearch[middle]==arrSearch[low]&&arrSearch[middle]==arrSearch[high])
return searchMinInOrder(arrSearch,low,high)
1 searchMinInOrder(arrSearch,low,high)
2 int result = arrSearch[low];
3 for(int i=low+1;i=<high;i++)
4 if(arrSearch[i]<result)
5 result = arrSearch[i];
6 end if
7 end for
8 return result;
本题在算法面试的时候经常会遇到,一定要注意数据为空、边界值、数组中的数重复,升序数组。