把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。
示例 1:
输入:[3,4,5,1,2]
输出:1
示例 2:
输入:[2,2,2,0,1]
输出:0
解法一:直接对其进行排序,输出下标为0的元素即可
int minArray(vector<int>& numbers)
{
sort(numbers.begin(),numbers.end());
return numbers[0];
}
解法二:遍历数组,找出最小元素输出
int minArray(int* numbers, int numbersSize)
{
int min=numbers[0];
for(int i=0;i<numbersSize;i++)
{
if(numbers[i]<min)
{
min=numbers[i];
}
}
return min;
}
直观来说,这两种解法都没有按照题目的要求,总是感觉和题目说的旋转没有丝毫关系,因此在面试的时候,这两种解法几乎是没有多大意义。我们来接着看解法三。
解法三:从题意来说,我们可以将数组分为两部分,并且这两部分都是排好序的。因此我们可以考虑用二分查找来解决。
int MinOrder(int* numbers, int left, int right)
{
int result = numbers[left];
for (int i = left + 1; i <= right; i++)
{
if (result > numbers[i])
{
result = numbers[i];
}
}
return result;
}
int minArray(int* numbers, int numbersSize)
{
if (numbers == NULL || numbersSize <= 0)
{
return -1;
}
int left = 0;
int right = numbersSize - 1;
int indexmid = left;
while (numbers[left] >= numbers[right])
{
if (right - left == 1)
{
indexmid = right;
break;
}
indexmid = ((right - left) >> 1) + left;
if (numbers[left] == numbers[right] && numbers[indexmid] == numbers[left])
{
return MinOrder(numbers, left, right);
}
if (numbers[indexmid] >= numbers[left])
{
left = indexmid;
}
else if (numbers[indexmid] <= numbers[right])
{
right = indexmid;
}
}
return numbers[indexmid];
}
我们在二分查找的时候注意考虑特殊情况,比如说找到的中间值即在第一个递增序列中又在第二个递增序列中的时候特殊处理。
比如说1,0,1,1,1
这种情况或者1,1,1,0,1
这种情况。