这套题的方法和它的前代是一模一样的,找到一个Gap,也就是分界点,这个分界点的前一个元素大于后一个元素。
在前代中我们逐步缩小Gap的范围的方法是比较num[l], num[mid], num[h]的值,由于前代中确保不会出现重复的元素,所以这种方法是可行的,但如果有重复元素就会出现无法确定Gap所处范围的问题,比如:
3, 1, 3, 3, 3;
3, 3, 3, 1, 3。
注意这两个样例,当num[l] == num[mid]的时候,我们没有办法确定Gap到底是在mid左还是mid右。
于是只好两边都找,返回两边找的值中的较小值。
由于前代中用的是循环来实现二分查找,此处需要两边都找,用递归较好实现,同时也做了一些优化(个人感觉相比前代更好懂些)。
class Solution {
public:
vector<int> Num;
int findMin(vector<int> & num) {
if (num.size() == 1) return num[0];
if (num[0] < num[num.size() - 1]) return num[0];
Num = num;
return findGap(0, Num.size() - 1);
}
int findGap(int l, int h) {
if (l == h - 1) return (Num[l] < Num[h] ? Num[l] : Num[h]); // 当当前区间只有两个值直接比较
int mid = (l + h) / 2;
if (Num[l] > Num[mid]) return findGap(l, mid);
else if (Num[l] < Num[mid]) return findGap(mid, h);
else return min(findGap(l, mid), findGap(mid, h)); // 如果无法确定范围
}
};