-
链接 : 原题
-
题意 : 给定一个山脉数组,即凸函数,寻找一个数值等于target的index。
-
思路 :
因为凸函数峰值的左右都是一个单调函数,所以只要找到峰值,再对两边分别进行二分查找就可。
凹凸函数找峰值,本来我是想用三分查找的,但是三分查找能确定峰值是double类型,即连续函数才适用的。整数点构成的凹凸函数,三分查找只能缩减一个区间。例如此题 :牛客算法周周练4 E题装备合成。
所以本次学到了一种 二分凹凸函数找极值 的方法。对于一个区间 [l , r] ,mid1 = (l + r)/2,我们再寻找一个mid2 = mid1 + 1。如果mid1 的值 > mid2 的值,那么 [mid2 , r] 是一个递减的区间;否则 [l, mid1]是一个递增的区间。
这样最后就能确定一个峰值peak。
最后再对左边递增区间二分查找,如果没找到再到右边二分查找。 -
代码:
/**
* // This is the MountainArray's API interface.
* // You should not implement it, or speculate about its implementation
* class MountainArray {
* public:
* int get(int index);
* int length();
* };
*/
class Solution {
public:
int findInMountainArray(int target, MountainArray &mountainArr) {
int l = 0, r = mountainArr.length() - 1;
while(r - l > 0){
int mid1 = l + (r-l)/2;
int mid2 = mid1 + 1;
if(mountainArr.get(mid1) > mountainArr.get(mid2)){
r = mid1;
}else{
l = mid2;
}
}
int left = 0, right = l;
int ans = -1;
while(left <= right){
int mid = (right + left)/2;
if(mountainArr.get(mid) == target){
ans = mid;
}
if(mountainArr.get(mid) > target){
right = mid - 1;
}else{
left = mid + 1;
}
}
if(ans == -1){
left = l + 1, right = mountainArr.length() - 1;
while(left <= right){
int mid = (right + left)/2;
if(mountainArr.get(mid) == target){
ans = mid;
}
if(mountainArr.get(mid) > target){
left = mid + 1;
}else{
right = mid - 1;
}
}
}
return ans;
}
};
- 遇到的问题:
(1)二分查找的判定条件以及 mid + 1 ,mid - 1等等太容易出错了。并且在单调区间内二分搜索的时候 mid = (l + r)/2,而不可是 l + (r-l)/2。
(2)第二次查找的时候区间不一样。