题目简述:
(这是一个 交互式问题 )
你可以将一个数组
arr称为 山脉数组 当且仅当:
arr.length >= 3- 存在一些
arr[0] < arr[1] < ... < arr[i - 1] < arr[i]的i使得:
arr[0] < arr[1] < ... < arr[i - 1] < arr[i]arr[i] > arr[i + 1] > ... > arr[arr.length - 1]给定一个山脉数组
mountainArr,返回 最小 的index使得mountainArr.get(index) == target。如果不存在这样的index,返回-1。你无法直接访问山脉数组。你只能使用
MountainArray接口来访问数组:
MountainArray.get(k)返回数组中下标为k的元素(从 0 开始)。MountainArray.length()返回数组的长度。调用
MountainArray.get超过100次的提交会被判定为错误答案。此外,任何试图绕过在线评测的解决方案都将导致取消资格。
题目链接:1095. 山脉数组中查找目标值
很明显是一个二分搜索算法的问题嘛!
我们先二分搜索找出山顶,然后再分别在山顶两侧各自应用二分搜索,这样至多启动三例二分搜索算法,就可以找出 target。
对于寻找山峰的二分查找,初始化 left = 0、right = MountainArray.length() - 1,
- 取
mid = left + (right - left) / 2 - 借助
mid + 1(或mid - 1也可以)判断mid处于上山还是下山,- 若
MountainArray.get(mid) < MountainArray.get(mid + 1),则mid处于上山段,收缩边界,令left = mid + 1 - 若
MountainArray.get(mid) > MountainArray.get(mid + 1),则mid处于下山段,收缩边界,令right = mid
- 若
- 回到第一步,直到
MountainArray.get(mid) > MountainArray.get(mid + 1)且MountainArray.get(mid) > MountainArray.get(mid - 1),此时mid即为山峰
对于第三步的条件,可以优化为 while (left < right),此时 left == right 之处即为山峰。
找到了山顶后的二分搜索算法这里就不单独描述了,标准的二分查找。
/**
* // This is MountainArray's API interface.
* // You should not implement it, or speculate about its implementation
* interface MountainArray {
* public int get(int index) {}
* public int length() {}
* }
*/
class Solution {
private int[] map;
private MountainArray mountainArr;
public int findInMountainArray(int target, MountainArray mountainArr) {
this.map = new int[mountainArr.length()];
this.mountainArr = mountainArr;
Arrays.fill(map, -1);
// 寻找山峰
int l = 0;
int r = mountainArr.length() - 1;
while (l < r) {
int mid = l + (r - l) / 2;
if (cache(mid) < cache(mid + 1)) {
l = mid + 1;
} else {
r = mid;
}
}
// 在山峰两侧分别二分搜索
int peak = l;
if (cache(peak) == target) return peak;
l = 0;
r = peak - 1;
while (l <= r) {
int mid = l + (r - l) / 2;
if (cache(mid) < target) {
l = mid + 1;
} else {
r = mid - 1;
}
}
if (cache(l) == target) return l;
l = peak + 1;
r = mountainArr.length() - 1;
while (l <= r) {
int mid = l + (r - l) / 2;
if (cache(mid) > target) {
l = mid + 1;
} else {
r = mid - 1;
}
}
if (l < mountainArr.length() && cache(l) == target) return l;
return -1;
}
private int cache(int index) {
if (map[index] == -1) {
int val = mountainArr.get(index);
map[index] = val;
return val;
} else {
return map[index];
}
}
}