解法1:二分查找
注:当重复度影响折半时,则逐个查找最小值。最优复杂度O(logn),最差O(n)
int findInTurn(int*numbers, int left, int right) {
int min = numbers[left];
for (int i = left+1; i<= right; i++)
if (min > numbers[i])
min = numbers[i];
return min;
}
int minArray(int* numbers, int numbersSize){
if (numbers == NULL || numbersSize <= 0)
return -1;
int left = 0, right = numbersSize-1;
int mid;
while (left < right) { //<=或<都可以
mid = (left + right)>>1;
if (numbers[mid] > numbers[right])
left = mid + 1;
else if (numbers[mid] < numbers[right])
right = mid; //不是mid+1,也许numbers[mid]就是最小值
else
return findInTurn(numbers, left, right);
}
return numbers[left];
}
C++版可参考如下程序:
class Solution {
private:
int findOneByOne(const vector<int>& nums, int left, int right) {
int min = nums[left];
for(int i = left+1; i < right; i++)
if(nums[i] < min)
min = nums[i];
return min;
}
public:
int findMin(vector<int>& nums) {
int len = nums.size();
//if (len == 0)
// return -1;
//if (len == 1)
// return nums[0];
int left = 0, right = len - 1;
int mid;
while (left < right) {
mid = (left + right)>>1;
if (nums[mid] == nums[left] && nums[mid] == nums[right])
return findOneByOne(nums, left, right);
else if (nums[mid] > nums[right])
left = mid + 1;
else
right = mid;
}
return nums[left];
}
};
如果不想另写类似findOneByOne()函数时,可以移一步处理,具体参考如下程序:
class Solution {
public:
int findMin(vector<int>& nums) {
int len = nums.size();
//if (len == 0)
// return -1;
//if (len == 1)
// return nums[0];
int left = 0, right = len - 1;
int mid;
while (left < right) {
mid = (left + right)>>1;
if (nums[mid] == nums[left] && nums[mid] == nums[right])
right--; //left++亦可
else if (nums[mid] > nums[right])
left = mid + 1;
else
right = mid;
}
return nums[left];
}
};
解法2:找转折点
int minArray(int* numbers, int numbersSize){
if (numbers == NULL || numbersSize <= 0)
return -1;
int i = 0, j = 1;
for (; i < numbersSize-1; i++, j++) {
if(numbers[i] <= numbers[j])
continue;
break;
}
if (j == numbersSize)
return numbers[0];
return numbers[j];
}