题目
二分查找法
public class Main {
public static void main(String[] args) {
Main main = new Main();
int [] nums = new int[] {1};
main.findPeakElement(nums);
}
public int findPeakElement(int[] nums) {
if (nums.length == 1) {
return 0;
}
// 一个无序数组存在多个峰值 得到任何一个即可, 并且相邻元素不相等
// 峰值只可能存在于三个位置 边界+峰值+下降序列 上升序列+峰值+下降序列 上升序列+峰值+下降序列
// 因此题目可以转变成寻找上升和下降序列, 来缩小峰值可能存在的范围, 提高查找效率
// 利用二分法
int left = 0;
int right = nums.length - 1;
int mid = 0;
while (left <= right) {
mid = left + (right - left) / 2;
if (mid - 1 < 0) {
// 左边是边界
if (nums[mid] > nums[mid + 1]) {
return mid;
} else {
left = mid + 1;
}
} else if (mid + 1 == nums.length) {
// 右边是边界
if (nums[mid] > nums[mid - 1]) {
return mid;
} else {
right = mid - 1;
}
} else {
if (nums[mid] < nums[mid - 1]) {
// mid位于下降序列 峰值在mid左侧
right = mid - 1;
} else if (nums[mid] < nums[mid + 1]) {
// mid位于上升序列 峰值在mid右侧
left = mid + 1;
} else {
return mid;
}
}
}
return mid;
}
}
基本思路
-
一看到题目能想到的就是遍历数组, 然后比较nums[i - 1], nums[i], nums[i + 1]三个值的大小关系, 判断是否是峰值, 但是显然这个方法太蠢了
-
扩展来想, 题目中的峰值不只一个, 同时峰值只可能存在于三个位置 边界+峰值+下降序列 上升序列+峰值+下降序列 上升序列+峰值+下降序列, 因此可以通过二分法缩小查找范围, 保证范围内一定存在一个峰值即可