题目描述
6、把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
解题思路:
1、题目考察的是查找和排序,数组旋转后,我们可以看成变成了两个非递减有序排列的子数组,且前面子数组所有元素都要大于后面的;一般在有序排列中查找某个元素,首先想到的是二分查找法,时间复杂度为O(logN)。
2、采用二分查找,找到数组的中间元素middle,针对题意进行分析
1)、如果中间元素middle大于第一个元素(说明前面已经排序),最小元素肯定位于middle的后面,将low指向中间元素middle,在后面的子数组中继续查找。
2)、如果中间元素middle小于第一个元素,同样可以肯定最小元素位于middle的前面,将high指向中间元素middle,在前面的子数组中继续查找。
3、问题关键是找到循环的结束条件,按照上述方式,low指向的子数组元素肯定大于high指向的子数组元素,最终low会指向前面数组的最后一个元素,high会指向后面数组的第一个元素,最终会指向两个相邻的元素,此时high指向的元素就是最小的元素,循环结束。
参考代码:
/*************************************************
Copyright:牛客网在线编程《剑指offer》
Author:zhouyuan
Date:2017-02-24
Description:旋转数组的最小数字
**************************************************/
#include <vector>
using namespace std;
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
if (rotateArray.empty()) {
return 0;
}
int low = 0;
int high = rotateArray.size() - 1;
int middle = 0;
if (rotateArray.at(low) < rotateArray.at(high)) { //说明已经是非递减排序,直接返回第一个最小元素
return rotateArray.at(low);
}
//二分查找
while (low < high) {
if (high - low == 1) {
middle = high;
break;
}
int middle = (low + high) / 2;
if (rotateArray.at(middle) >= rotateArray.at(low)) {
low = middle;
}
else if (rotateArray.at(middle) <= rotateArray.at(low)) {
high = middle;
}
}
return rotateArray.at(middle);
}
};