题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{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}的旋转,前半部分始终大于等于后半部分,符合部分有序。仍然可以使用二分查找法,可判断中间位置在前半部分还是在后半部分,如果在前半部分则min 在后半部分,否则在前半部分。这样进行二分查找。
但是有特殊情况,当为这种情况时{1,1,1,0,1}或者{1,0,1,1,1}使用二分查找不会得到正确的结果,这种情况只能使用顺序查找了。
解题代码
#include <vector>
#include <iostream>
using namespace std;
/*
题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
*/
class SolutionMinNum {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
if (rotateArray.size() == 0)
return 0;
int low = 0;
int high = rotateArray.size()-1;
int mid = low;
while (rotateArray[low] >= rotateArray[high])
{
if (high - low == 1)
{
mid = high;
break;
}
int mid = (low + high)/2;
//特殊情况,{1,1,1,0,1}(只使用二分查找碰见可以查找成功,会走第一个if) 或者 {1,0,1,1,1}(只使用二分查找失败)需要使用顺序查找
if (rotateArray[low] == rotateArray[mid] &&
rotateArray[mid] == rotateArray[high])
return minInOrder(rotateArray, low, high);
if (rotateArray[mid] >= rotateArray[low]) //最小值在后边
low = mid;
else if (rotateArray[mid] <= rotateArray[high]) //最小值在前边
high = mid;
}
return rotateArray[mid];
}
int minInOrder(vector<int> & rotateArray, int low, int high) //顺序查找最小值
{
int min = rotateArray[low];
for (int i = low +1; i <=high; i++)
{
if (min > rotateArray[i])
min = rotateArray[i];
}
return min;
}
};
int main(int argc, char *argv[])
{
SolutionMinNum MinNum;
vector<int> arr1 = { 3,4,5,1,2 };
vector<int> arr2 = { 1, 1, 1, 0, 1 };
vector<int> arr3 = { 1, 0, 1, 1, 1 };
int min = MinNum.minNumberInRotateArray(arr1);
cout << min << endl;
min = MinNum.minNumberInRotateArray(arr2);
cout << min << endl;
min = MinNum.minNumberInRotateArray(arr3);
cout << min << endl;
system("pause");
return EXIT_SUCCESS;
}