剑指 Offer 11. 旋转数组的最小数字
个人思路
题意
题目中的数组被分割成两部分,且两部分均为递增序列,找出序列中的最小元素,要利用递增数组的特性,要采用二分查找
思路
- 循环条件:根据旋转数组的特点,序列应满足第一个元素大于最后一个元素(特例1,2,3,4,5)
- 二分查找(此处的mid,left,right表示数值):如果mid大于等于left,说明mid属于前一个递增数组,最小元素应该在mid 的后面;如果mid小于等于right,说明mid属于后一个递增数组,最小元素应该在mid前面,也可能就是mid
- 循环终止条件:当right和left相差1时,此时left指向前一个递增数组的最后一个元素,right指向后一个递增数组的第一个元素,right即为最小元素,返回right
注意
此题有许多特例
- 当数组为已经排序的数组,即1,2,3,4,5,此时第一个元素小于最后一个元素,应返回left
- 当最小元素夹在相同元素中,即10,1,10,10,10,此时会出现mid== left ==right的情况,此时无法判断当前的mid在哪一个递增数组中,只能顺序遍历
个人错误思路代码
- 判断条件没有搞清楚
- 对于mid== left ==right的特例没有处理好
class Solution {
public:
const int inf = 0x3fffffff;
int minArray(vector<int>& numbers) {
if(numbers.size() == 0){
return 0;
}
int left = 0, right = numbers.size() - 1;
if(left == right){
return numbers[left];
}
int temp = inf;
if(numbers[left] <= numbers[right]){
temp = numbers[left];
}
while(left <= right){
int mid = (left + right) / 2;//下标
int midData = numbers[mid];//数据
//cout << left << " " << mid << " " << right << endl;
if(right - left == 1){//此时是最小元素,即分界处
if(numbers[right] > temp){
return temp;
}else{
return numbers[right];
}
}
if(midData >= numbers[left]){//说明当前元素在前面的递增数组中,最小元素则在后半段
left = mid;
continue;
}
if(midData <= numbers[right]){
right = mid;
continue;
}
}
return numbers[left];
}
};
正确解题代码
class Solution {
public:
int minArray(vector<int>& numbers) {
if(numbers.size() == 0){
return 0;
}
int left = 0, right = numbers.size() - 1;
if(numbers[left] < numbers[right]){//说明数组是排序的
return numbers[left];
}
while(numbers[left] >= numbers[right]){
int mid = (left + right) >> 1;
//cout << left << " " << mid << " " << right << endl;
if(right - left == 1){//左右指针位置相差1
return numbers[right];
}
if(numbers[left] == numbers[mid] && numbers[mid] == numbers[right]){//当三个指针数值相同时,无法判断最小元素的位置
int temp = numbers[left];
for(int i = left + 1; i < right; ++i){
if(numbers[i] < temp){
temp = numbers[i];
}
}
return temp;
}
if(numbers[mid] >= numbers[left]){//说明当前元素属于前一个递增数组中,最小元素在当前元素后面
left = mid;
continue;
}
if(numbers[mid] <= numbers[right]){//说明当前元素属于后一个递增数组,最小元素可能是当前元素,也可能在当前元素前面
right = mid;
continue;
}
}
return numbers[right];
}
};
测试样例
input:1,2,3,4,5
output:1
input:10,1,10,10,10
output:1