剑指 Offer 11. 旋转数组的最小数字 - 力扣(LeetCode) (leetcode-cn.com)
首先放上运行结果
思路
如果数列确实经过了旋转且无重复数字,那么它满足如下特点:
1. 从最小元素到数列末尾元素,均小于首元素
2. 从首元素到最大元素,均大于等于首元素
根据这两点,我们可以进行二分查找,设首元素所在位置为front,末尾元素所在位置为back,中间元素所在位置为mid。if numbers[mid] < numbers[front], then back = mid; if numbers[mid] > numbers[front], then front = mid;如此进行,直到back == front + 1,此时front位置为最大元素,back位置为最小元素。
如果数列并未经过旋转,那么整个数列是递增的,首元素一定小于末尾元素,此时直接返回首元素即可。
如果数列中有大量重复元素,比如numbers[mid] == numbers[front]的情况,此时最小元素可能出现在mid左边,也可能出现在mid右边,我们无法确定它的位置,只能暴力查找。
代码
class Solution {
public:
int minArray(vector<int>& numbers) {
int front = 0, back = numbers.size() - 1, halfsize, mid;
if(numbers[front] < numbers[back]) return numbers[front];
while (halfsize = (back - front) / 2) {
mid = front + halfsize;
if (numbers[mid] == numbers[front]) {
int _min = numbers[front];
for(int i = front + 1; i <= back; ++i) numbers[i] < _min ? _min = numbers[i] : NULL;
return _min;
}
numbers[mid] > numbers[front] ? front = mid : back = mid;
}
return numbers[back];
}
};