题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。
–
例如,数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
分析:
我们注意到旋转之后的数组实际上可以划分为两个排序的子数组,而且前面子数组的元素都大于或者等于后面子数组的元素。和二分查找法一样,我们用两个指针分别指向数组的第一个元素和最后一个元素。按照这种思路,第一个指针总是指向前面递增数组的元素,而第二个指针总是指向后面递增数组的元素。最终第一个指针将指向前面数组的最后一个元素,而第二个指针会指向后面子数组的第一个元素。也就是它们最终会指向两个相邻的元素,而第二个指针指向的刚好是最小的元素。这就是循环结束的条件。
注意:考虑特殊情况(见代码)
java参考代码如下:
package chapter2;
public class P82_MinNumberInRotatedArray {
//在旋转数组中查找target,找到返回下标,未找到返回-1.
public static int searchinrotatedarray(int[] data,int target){
int left=0,right=data.length-1;
while (left<=right){
int mid=left+(right-left)/2;
if(data[mid]==target) return mid;
else if(data[mid]<data[right]){//右边部分有序
if(data[mid]<target&&target<=data[right])
left=mid+1;
else
right=mid-1;
}else if(data[mid]>data[right]){//左边部分有序
if(data[left]<=target&&target<data[mid])
right=mid-1;
else
left=mid+1;
}else//有重复值的情况
--right;
}
return -1;
}
//找到旋转数组的最小值
public static int findMin(int[] data){
int left=0,right=data.length-1;
while (left<right){
int mid=left+(right-left)/2;
if(data[mid]<data[right])
right=mid;
else if(data[mid]>data[right]){
left=mid+1;
}else if(data[mid]==data[right]){
--right;
}
}
return data[left];
}
public static void main(String[] args){
int[] data={2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2};
int[] data1={1,1,3,1,1,1,1};
int target=3;
System.out.println(searchinrotatedarray(data,target));
System.out.println(findMin(data));
System.out.println(findMin(data1));
}
}
参考处(博客评论):http://www.cnblogs.com/grandyang/p/4040438.html
代码实现如下:
int Min(int *numbers,int length)
{
if(numbers==nullptr || length<=0)
throw new std::exception("Invalid parameters.");
int index1=0;
int index2=length-1;
int indexMid=index1;//考虑到如果是旋转0个元素,即原数组的情况。
while(numbers[index1]>=numbers[index2])
{
if(index2-index1==1)
break;
indexMid=(index1+index2)/2;
//如果下标index1、index2和indexMid指向的三个数字相等,
//则只能顺序查找
if(numbers[index1]==numbers[index2] && numbers[indexMid]==numbers[index1])
return MinInOrder(numbers,index1,index2);
if(numbers[indexMid]>=numbers[index1])
index1=indexMid;
else if(numbers[indexMid]<=numbers[index2])
index2=indexMid;
}
return numbers[indexMid];
}
int MinInOrder(int* numbers,int index1,int index2)
{
int result=numbers[index1];
for(int index=index1;index<=index2;++index)
{
if(result>numbers[index])
result=numbers[index];
}
return result;
}
测试用例:
a.功能测试(输入的数组是升序排序数组的一个旋转,数组中有重复数字或者没有重复数字)。
b.边界值测试(输入的数组是一个升序排序的数组,只包含一个数字的数组)。
c.特殊输入测试(输入nullptr指针)。