题目大意: 寻找递增的旋转数组里面最小的数
解题思路:折半查找。
有序的旋转数组前半部分和后半部分都是递增的序列。数组第一个元素要大于等于最后一个元素。否则数组本身就是个递增的序列,第一个元素就是最小数
如果不是递增序列,则取中间数。
1.如果中间数大于数组的第一个元素,说明最小数存在后半段,范围缩小到中间数到最后一个元素左开右闭区间
2.如果中间数小于数组的第一个元素,说明最小数存在前半段,范围缩小到第一个元素和中间数闭区间左开右闭区间。
3.如果中间数等于数组第一个元素,需要特殊处理。
3.1 如果中间数大于数组最后一个元素,说明最小数存在后半段, 范围缩小到中间数到最后一个元素左开右闭区间
3.2 如果中间数等于数组最后一个元素,则需分别找出这第一个元素到中间数,和中间数到最后一个元素这两个区间的最小数,然后对这两个最小数进行比较,最后取最小值。
可以用递归实现:
#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;
class Solution {
public:
int findMin(vector<int> &num) {
return assistFindMin(num, 0, num.size() - 1);
}
private:
int assistFindMin(vector<int> &num, int begin, int end) {
if(begin == end || num[begin] < num[end])
return num[begin];
int mid = (begin + end) >> 1;
if(num[mid] > num[begin])
return assistFindMin(num, mid + 1, end);
else if(num[mid] < num[begin])
return assistFindMin(num, begin + 1, mid);
else {
if(num[mid] > num[end])
return assistFindMin(num, mid + 1, end);
else
return min(assistFindMin(num, begin, mid), assistFindMin(num, mid + 1, end));
}
}
int min(int a, int b) {
return a <= b ? a : b;
}
};
int main() {
Solution solution;
int array1[5] = {1, 2, 3, 4, 5};
int array2[5] = {2, 2, 2, 2, 2};
int array3[7] = {4, 5, 6, 7, 0, 1, 2};
int array4[5] = {1, 0, 1, 1, 1};
vector<int> num1(array1, array1 + sizeof(array1) / sizeof(array1[0]));
vector<int> num2(array2, array2 + sizeof(array2) / sizeof(array2[0]));
vector<int> num3(array3, array3 + sizeof(array3) / sizeof(array3[0]));
vector<int> num4(array4, array4 + sizeof(array4) / sizeof(array4[0]));;
printf("test 1: %d\n", solution.findMin(num1));
printf("test 2: %d\n", solution.findMin(num2));
printf("test 3: %d\n", solution.findMin(num3));
printf("test 4: %d\n", solution.findMin(num4));
return 0;
}
非递归的话,3.2步需要顺序比较:
#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;
class Solution {
public:
int findMin(vector<int> &num) {
int begin = 0;
int end = num.size() - 1;
int mid = begin;
while(begin <= end && num[begin] >= num[end]) {
if(begin == end)
return num[begin];
mid = (begin + end) >> 1;
if(num[mid] > num[begin])
begin = mid + 1;
else if(num[mid] < num[begin]) {
begin++;
end = mid;
} else {
if(num[mid] > num[end])
begin = mid + 1;
else {
int minVal = num[begin];
for(int i = begin + 1; i <= end; i++) {
if(minVal > num[i])
minVal = num[i];
}
return minVal;
}
}
if(num[begin] < num[end])
return num[begin];
}
return num[mid];
}
};
int main() {
Solution solution;
int array1[5] = {1, 2, 3, 4, 5};
int array2[5] = {2, 2, 2, 2, 2};
int array3[7] = {4, 5, 6, 7, 0, 1, 2};
int array4[5] = {1, 0, 1, 1, 1};
vector<int> num1(array1, array1 + sizeof(array1) / sizeof(array1[0]));
vector<int> num2(array2, array2 + sizeof(array2) / sizeof(array2[0]));
vector<int> num3(array3, array3 + sizeof(array3) / sizeof(array3[0]));
vector<int> num4(array4, array4 + sizeof(array4) / sizeof(array4[0]));;
printf("test 1: %d\n", solution.findMin(num1));
printf("test 2: %d\n", solution.findMin(num2));
printf("test 3: %d\n", solution.findMin(num3));
printf("test 4: %d\n", solution.findMin(num4));
return 0;
}