您的位置:首页 > Web前端

剑指offer——旋转数组最小数字问题

2015-08-30 11:59 253 查看
今天做到旋转数字最小数字时,看到需要考虑的边界有些麻烦,因而分析总结一下。

旋转数组其实就是一个递增排序数组的旋转,例如{3,4,5,1,2}即为{1,2,3,4,5}的一个旋转数组。

旋转数组有一个特性:包含两个递增子序列,因而可以考虑用二分查找简化。设置三个指针low,high,middle,low指向数组低部分,high指向数组高部分,middle指向high,low中间部分。若middle指向数据>low指向数据,则说明最小值位于middle右侧部分;若middle指向数据小于high指向数据,则说明最小值位于middle左侧部分。以上这些很好理解。

但是有两种特殊情况:

1. 数组为一个有序数组。即把数组前面0个元素放在后面。

2. 数组中有多个重复值。例如{1,0,1,1,1}和{1,1,1,0,1}均为{0,1,1,1,1}的旋转数组。

对于第一种情况,上述解决方法仍然适用。

而对于第二种情况,我们无法通过三个指针的数据判断最小值的位置,这个时候,需要退化成顺序查找,让high- -或者low++。

最终可得到代码:

class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
if (rotateArray.size()<=0) {
return 0;
}
int low=0;
int high=rotateArray.size()-1;
int middle;
while (high>=low) {
if (high==low) {
break;
}
middle=(high+low)/2;
if (rotateArray[middle]<rotateArray[high] && high>=low) {
high=middle;
}
else if (rotateArray[middle]==rotateArray[high] && high>=low) {
high--;
}
else if (rotateArray[middle]>rotateArray[low] && high>=low) {
low=middle;
}
else if (rotateArray[middle]==rotateArray[low] && high>=low){
low++;
}
}
return rotateArray[high];
}
};


对比一下前几天的一道面试题,一个数组前半部分递减,后半部分递增,求最小值。其实拐角处就是最小值。对于这些基本有序的数组,首先要考虑用二分查找来进行简化,其实上述问题就是个变形的二分查找,但是middle指针并不是于high或low指针指向内容进行比较,而是与middle+1指针进行比较,来判断现在middle在递增序列还是递减序列,然后改变high或low指针即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  旋转数组