三分找极值点:https://blog.csdn.net/pi9nc/article/details/9666627
解题思路:
1.先用三分查找,找到极值点的位置pt
2.根据pt将数组分成两段,先对第一段[0,pt]二分查找target,找到立即返回
3.如果第一段没有找到target,则二分查找第二段[pt,arr.length-1]
这样满足查询不超过100次的要求吗?
答:三分 复杂度据说是2log3(n) ,二分复杂度是2log2(n)。
那么找极值点 最多需要查找 2log3(n) = 2log3(10000) ≈ 2*9 = 18 次
二分最多需要调用 2*log2(10000) ≈ 2*14 = 28 次
18 + 28 < 100,所以这个方案是满足要求的。
class Solution {
int target;
MountainArray mountainArr;
public int findInMountainArray(int target, MountainArray mountainArr) {
int len = mountainArr.length();
int l = 0;
int r = len-1;
this.target = target;
this.mountainArr=mountainArr;//1. 找极值点位置
while(l+1<r)
{
int mid = mountainArr.get((l+r)/2);
int mmid = mountainArr.get(((l+r)/2+r)/2);
if(mid>mmid)
{
r = ((l+r)/2+r)/2;
}else{
l = (l+r)/2;
}
}
int ll = mountainArr.get(l);
int rr = mountainArr.get(r);
int pt = ll>rr?l:r;
//pt是极值点
//二分左边,找到返回
int rs = two_divide(0,pt,true);
if(rs!=-1) return rs;
//二分右边
rs = two_divide(pt+1,len-1,false);
return rs;
}private int two_divide(int l, int r,boolean up) {
if(up){ //递增
while(l<=r)
{
int mid = (l+r)/2;
int mid_value = mountainArr.get(mid);
if(target<mid_value)
{
r = mid-1;
}else if(target>mid_value){
l = mid+1;
}else{
return mid;
}
}
return -1;
}else{ //递减
while(l<=r)
{
int mid = (l+r)/2;
int mid_value = mountainArr.get(mid);
if(target>mid_value)
{
r = mid-1;
}else if(target<mid_value){
l = mid+1;
}else{
return mid;
}
}
return -1;
}
}
}