题目描述:
解题思路:当数组有重复元素时,只要Mindex与Rindex和Lindex下标代表的元素都不相等时还是可以继续使用二分查找,但是当Mindex与Rindex和Lindex下标代表的元素都相等时,这时使用就不能使用二分查找,需要将这一段区间单独取出来使用顺序遍历的方法算出数组中最小值。
代码如下:
//顺序遍历求出最小值
int MinInorder(int* Nums,int NumsSize){
int ret=0;
for(int i=0;i<NumsSize;i++){
if(Nums[ret]>Nums[i])
ret=i;
}
return Nums[ret];
}
int findMin(int* nums, int numsSize) {
assert(nums||numsSize<=0);
int Lindex=0;
int Rindex=numsSize-1;
int Mindex=Lindex;
//当左边值大于右边值时,且Rindex>Lindex,则继续二分查找
while(nums[Lindex]>=nums[Rindex]&&Rindex>Lindex){
//当Lindex和Rindex相邻时,更新Mindex,并跳出循环
if(Rindex-Lindex==1){
Mindex=Rindex;
break;
}
//更新Mindex
Mindex=Lindex+(Rindex-Lindex)/2;
//若Lindex,Mindex,Rindex三个下标表示的元素的大小都相等时,这时就不能再使用二分查找去
//划分新的区间,要使用顺序遍历的方法求出最小元素
if(nums[Mindex]==nums[Lindex]&&nums[Mindex]==nums[Rindex]){
//返回最小值
return MinInorder(nums+Lindex,Rindex-Lindex);
}
//若中间值大于等于左边值,则证明小区间在Mindex的右边,更新Lindex
else if(nums[Mindex]>=nums[Lindex]){
Lindex=Mindex;
}
//若中间值小于等于右边值,则证明小区间在Mindex的左边, 更新Rindex
else if(nums[Mindex]<=nums[Rindex]){
Rindex=Mindex;
}
}
//返回最小值
return nums[Mindex];
}
剑指offer:面试题8:旋转数组最小值