public class FindMountainArray_1095 {
public static void main(String[] args) {
// int[] array = { 1, 3, 5, 4, 3, 2, 1 };
// int[] array = { 1, 2, 3, 4, 5, 3, 1 };
int[] array = { 0, 1, 2, 4, 2, 1 };
int target = 3;
MountainArray mountainArray = new MountainArrayImpl(array);
System.out.println(findInMountainArray(target, mountainArray));
}
public static int findInMountainArray(int target, MountainArray mountainArray) {
int len = mountainArray.length();
// 1.用二分法找到mountaninTop山顶下标
int top = findMountainTop(mountainArray, 0, len - 1);
// 2.然后对左边升序数组二分查找target目标下标
int res = findAscArray(mountainArray, 0, top, target);
// 找到target直接返回
if (res != -1) {
return res;
}
// 3.对右边降序数组二分查找target目标下标
return findDecArray(mountainArray, top + 1, len - 1, target);
}
/**
* 二分法查找最大元素
* @param mountainArr 山峰数组
* @param left 数组最小下标
* @param right 数组最大下标
* @return 最大元素下标
*/
public static int findMountainTop(MountainArray mountainArr, int left, int right) {
while (left < right) {
// 取左中位数
int mid = left + (right - left) / 2;
// 左中位数和后面一位比较,确定下一次查找范围
if (mountainArr.get(mid) < mountainArr.get(mid + 1)) {
// 山顶在右边,去右边查找
left = mid + 1;
} else {
// 去左边查找,需要包含mid,因为mid可能是最大值
right = mid;
}
}
// 最后left=right
return left;
}
/**
* 二分法查找升序数组中的目标值
* @param mountainArr 山峰数组
* @param left 数组最小下标
* @param right 数组最大下标
* @param target 目标值
* @return 目标值下标
*/
public static int findAscArray(MountainArray mountainArr, int left, int right, int target) {
while (left < right) {
// 取左中位数
int mid = left + (right - left) / 2;
// 左中位数和后面一位比较,确定下一次查找范围
if (mountainArr.get(mid) < target) {
// 山顶在右边,去右边查找
left = mid + 1;
} else {
// 去左边查找,需要包含mid,因为mid可能是最大值
right = mid;
}
}
// 最后left=right
// 因为不确定区间缩为一个之后,是否找到target,所以需要判断
if (mountainArr.get(left) == target) {
return left;
}
return -1;
}
/**
* 二分法查找降序数组中的目标值
* @param mountainArr 山峰数组
* @param left 数组最小下标
* @param right 数组最大下标
* @param target 目标值
* @return 目标值下标
*/
public static int findDecArray(MountainArray mountainArr, int left, int right, int target) {
while (left < right) {
// 取左中位数
int mid = left + (right - left) / 2;
// 左中位数和后面一位比较,确定下一次查找范围
if (mountainArr.get(mid) > target) {
// 去右边查找
left = mid + 1;
} else {
// 去左边查找,需要包含mid,因为mid可能是最大值
right = mid;
}
}
// 最后left=right
// 因为不确定区间缩为一个之后,是否找到target,所以需要判断
if (mountainArr.get(left) == target) {
return left;
}
return -1;
}
}
class MountainArrayImpl implements MountainArray {
private int[] array;
private int length;
public MountainArrayImpl(int[] array) {
this.array = array;
this.length = array.length;
}
@Override
public int get(int index) {
return this.array[index];
}
@Override
public int length() {
return this.length;
}
}
interface MountainArray {
public int get(int index);
public int length();
}
相关文章: