LeetCode:Find Peak Element - 寻找一个数组内的顶点

1、题目名称

Find Peak Element(寻找一个数组内的顶点)

2、题目地址

https://leetcode.com/problems/find-peak-element/

3、题目内容

英文:

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

Given an input array where 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.

You may imagine that num[-1] = num[n] = -∞.

中文:

在一个数组内,如果某元素比它左右两个元素都大,则称该元素为一个“顶点”。现给出一个相邻元素一定不相同的数组,找出一个顶点元素并返回它的索引。一个数组中可能包含多个顶点,在这种情况下返回任意一个顶点的坐标即可。你可以假定第-1个元素和第n个元素是负无穷(这句话的意思就是最左边的元素假定它“再左边”还有一个比它小的元素,最右边的元素同理)。

例如:给定数组 [1, 2, 3, 1],则元素3是一个顶点,应返回它的索引值2

4、解题方法1

最容易想到的办法自然是自左至右遍历数组,如果某元素比它左边和右边的元素大,则该元素必为顶点。返回找到的第一个顶点即可。

Java代码如下:

/**
 * @功能说明:LeetCode 162 - Find Peak Element
 * @开发人员:Tsybius2014
 * @开发时间:2015年11月4日
 */
public class Solution {
    
    /**
     * 寻找顶点
     * @param nums
     * @return
     */
    public int findPeakElement(int[] nums) {
        
        if (nums == null) {
            return -1;
        } else if (nums.length == 0) {
            return -1;
        } else if (nums.length == 1) {
            return 0;
        } else if (nums[0] > nums[1]) {
            return 0;
        } else if (nums[nums.length - 1] > nums[nums.length - 2]) {
            return nums.length - 1;
        }
        
        for (int i = 1; i < nums.length - 1; i++) {
            if (nums[i - 1] <= nums[i] && nums[i + 1] <= nums[i]) {
                return i;
            }
        }
        
        return -1;
    }
}

4、解题方法2

另一种方法是使用二分查找法解决问题。这个方法利用了题目中的如下性质:

1)最左边的元素,它“更左边”的元素比它小(负无穷),我们认为它是一个增长的方向

2)最右边的元素,它“更右边”的元素比它小(也是负无穷),我们认为它是一个下降的方向

根据这两点我们可以判断:最左边和最右边的元素围成的区域内,必有至少一个顶点

现在我们找到中点 nums[mid],将它与 nums[mid + 1] 作比较,如果前者较小,则方向是增长,与最左边的元素是一致的,就把左边界挪到mid+1的位置;否则与最右边的元素一致,将右边界挪到mid的位置。

这个方法的原理就是当左边界方向为“增长”,右边界方向为“下降”时,二者围出的区域必有一个顶点。我们可以写出如下Java代码实现此方法:

/**
 * @功能说明:LeetCode 162 - Find Peak Element
 * @开发人员:Tsybius2014
 * @开发时间:2015年11月4日
 */
public class Solution {
    
    /**
     * 寻找顶点
     * @param nums
     * @return
     */
    public int findPeakElement(int[] nums) {
        
        if (nums == null) {
            return -1;
        } else if (nums.length == 0) {
            return -1;
        } else if (nums.length == 1) {
            return 0;
        } 

        int left = 0;
        int mid = 0;
        int right = nums.length - 1;
        
        while (left < right) {
            mid = left + (right - left) / 2;
            if (nums[mid] < nums[mid + 1]) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        
        return left;
    }
}

本题也可以使用递归的方式进行二分搜索。

END

你可能感兴趣的:(LeetCode,数组,二分搜索,#126,顶点)