题目链接:https://leetcode.com/problems/find-peak-element/ 题目:

A peak element is an element that is greater than its neighbors.

num[i] ≠ num[i+1], find a peak element and return its index.

The array may contain multiple peaks, in that case return the index to any one of the peaks is fine.

num[-1] = num[n] = -∞.[1, 2, 3, 1], 3 is a peak element and your function should return the index number 2.

Note:

Your solution should be in logarithmic complexity.

思路:

可能包含多个极值点(peak),只要取任意一个就行。假设只有一个peak,用二分查找根据mid元素单增单减的关系可以判断peak在mid的左边还是右边。如果不止一个peak,用二分法划分也不会将查找区间[left,right]划到没有peak的区间。时间复杂度为O(logn)。
算法:

public int findPeakElement(int[] nums) {
		int index = -1;
		int l = 0, h = nums.length - 1, m = 0;
		while (l <= h) {
			m = (l + h) / 2;
			int r = isPeakElement(nums, m);//判断i跟左右元素关系
			if (r == 0) {
				return m;
			} else if (r == -1) {//单减 peak在左边
				h = m - 1;
			} else if (r == 1) {//单增peak在右边
				l = m + 1;
			}
		}
		return index;
	}

	/**
	 * 判断i跟左右元素关系
	 * -1代表单减 0代表是peak 1代表单增
	 */
	public int isPeakElement(int[] nums, int i) {
		if (nums.length - 1 == i) { // 如果在最右边
			if (nums.length - 2 >= 0 && nums[nums.length - 2] < nums[nums.length - 1])//最后一个元素且比前一个元素大,是peak
				return 0;
			else if (nums.length - 2 < 0)//单元素肯定是peak
				return 0;
			else if (nums.length - 2 >= 0 && nums[nums.length - 2] < nums[nums.length - 1]) {
				return -1;
			}
		}
		if (0 == i) { // 如果在最左边
			if (i + 1 < nums.length && nums[i + 1] < nums[i])
				return 0;
			else if (i + 1 >= nums.length)
				return 0;
			else if (i + 1 < nums.length && nums[i + 1] > nums[i]) {
				return 1;
			}
		}
		// 否则左右都有数
		if (nums[i] > nums[i - 1]) {
			if (nums[i] > nums[i + 1])
				return 0;
			else
				return 1;
		} else {
			if (nums[i] > nums[i + 1])
				return -1;
			else
				return 1;
		}