75. Find Peak Element(二分法)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lighthear/article/details/79396866

LintCode

Description

There is an integer array which has the following features:

  • The numbers in adjacent positions are different.
  • A[0] < A[1] && A[A.length - 2] > A[A.length - 1].

We define a position P is a peak if:

A[P] > A[P-1] && A[P] > A[P+1]

Find a peak element in this array. Return the index of the peak.

 Notice
  • It's guaranteed the array has at least one peak.
  • The array may contain multiple peeks, find any of them.
  • The array has at least 3 numbers in it.
Example

Given [1, 2, 1, 3, 4, 5, 7, 6]

Return index 1 (which is number 2) or 6 (which is number 7)

Challenge 

Time complexity O(logN)

Solution

这道题也是经典二分法例题的变形,由于mid位置的取值总共分为四种情况,上升(向右找峰),下降(向左找峰),峰值(返回峰值),谷值(向两边都可以找到峰)。由题意至少三个数而且必有峰,因此一定可以在缩小到三个数的时候找到峰值。可以用二分法缩小范围解决这个问题。

Java

public class Solution {
    /*
     * @param A: An integers array.
     * @return: return any of peek positions.
     */
    public int findPeak(int[] A) {
        // write your code here
        int start = 0, end = A.length - 1;
        while (start + 1 < end) {
            int mid = start + (end - start) / 2;
            //如果上升,右边至少一个峰
            if (A[mid - 1] < A[mid] && A[mid] < A[mid + 1]) {
                start = mid;
            } else if (A[mid - 1] > A[mid] && A[mid] > A[mid + 1]) {
                //如果下降,左边至少一个峰
                end = mid;
            } else if (A[mid - 1] < A[mid] && A[mid] > A[mid + 1]) {
                //如果是峰,则返回mid
                return mid;
            } else {
                //如果是谷,则左右都至少有一个峰,向左向右缩小范围均可
                //end = mid;
                start = mid;
            }
        }
        return -1;
    }
}

-------------------------------------------------------------------------

LeetCode

Description

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] = -∞.

For example, in array [1, 2, 3, 1], 3 is a peak element and your function should return the index number 2.

click to show spoilers.

Note:

Your solution should be in logarithmic complexity.

Solution

LeetCode这道题不像LintCode中的那道题有规定至少三个元素,并且先增后减(即一定有峰)的情况。因此存在一个元素或者单调增/减的情况。解法如下:(此解法也适用LintCode,思想就是不断缩小范围找到最大值)

class Solution {
    public int findPeakElement(int[] nums) {
        if (nums == null || nums.length == 0) {  
            return -1;  
        }  
        int start = 0, end = nums.length - 1;       // 数组长度至少为1  
        //当数组中至少有3个数时才进入循环,因此mid不会有越界的情况发生  
        while (start + 1 < end) {  
            int mid = start + (end - start) / 2;  
            //如果是下降的,则将向左找峰  
            if (nums[mid] < nums[mid - 1]) {  
                end = mid;  
            } else if (nums[mid] < nums[mid + 1]) {  
                //如果是上升的,则向右找峰  
                start = mid;  
            } else {  
                //如果是峰值则返回mid,或者向左/向右缩小范围  
                //return mid;  
                end = mid;  
            }  
        }  
        //范围缩小到两个数时取出较大的,则为峰  
        if (nums[start] < nums[end]) {  
            return end;  
        } else {   
            return start;  
        }  
    }
}

猜你喜欢

转载自blog.csdn.net/lighthear/article/details/79396866