这道题里面有个隐藏条件:nums[-1] = nums[n] = -∞, 这就意味着数组最边上的两个数也有可能符合条件被返回,算法如下:

    public int findPeakElement(int[] nums) {
        int i=0;
        for(;i<nums.length-1;i++){
            if(nums[i]>nums[i+1])
                return i;
        }
        return i;
    }

但是题目要求:时间复杂度必须是O(log n),其实就是在考察binary search。

1. If you find your right neighbor is smaller than you, your neighbor will never be an candidate, but you might be, so end = mid.

2. If you find your right neighbor is  bigger than you, you will never be an candidate, but your neighbor might be, so start =mid+1.

Binary Search的算法如下,时间复杂度O(log n):

    public int findPeakElement(int[] nums) {
        if (nums.length == 0)
            return 0;
        int start = 0, end = nums.length - 1;
        int mid = (start + end) / 2;
        while (start < end) {
            if (nums[mid] > nums[mid + 1]) {
                end = mid;
            } else {
                start = mid + 1;
            }
            mid = (start + end) / 2;
        }
        return mid;
    }
    public int findPeakElement(int[] nums) {
        return helper(nums, 0, nums.length-1);
    }
    
    private int helper(int[] nums, int l, int r){
        if(l==r)
            return l;
        int mid = (l+r)/2;
        if(nums[mid]<nums[mid+1]){
            return helper(nums, mid+1, r);
        }
        else{
            return helper(nums, l, mid);
        }
    }

利用万能模版:

class Solution {
    public int findPeakElement(int[] nums) {if(nums.length==1)
            return 0;
        int l=0, r=nums.length-1;
        while(l+1<r){
            int mid = (l+r)/2;
            if(nums[mid]<nums[mid+1]){
                l=mid;
            }
            else
                r=mid;
        }
        if(nums[l]>nums[l+1])
            return l;
        else
            return r;
    }
}

 

那么如果题目变一变,求最底peak呢?只要改动一个符号即可:

1. If you find your right neighbor is bigger  than you, your neighbor will never be an candidate, but you might be, so end = mid.

2. If you find your right neighbor is smaller than you, you will never be an candidate, but your neighbor might be, so start =mid+1.

    public int findPeakElement(int[] nums) {
        if (nums.length == 0)
            return 0;
        int start = 0, end = nums.length - 1;
        int mid = (start + end) / 2;
        while (start < end) {
            if (nums[mid] < nums[mid + 1]) {  //only change from ">" to "<"
                end = mid;
            } else {
                start = mid + 1;
            }
            mid = (start + end) / 2;
        }
        return mid;
    }

 

    public int findPeakElement(int[] nums) {
        return helper(nums, 0, nums.length-1);
    }
    
    private int helper(int[] nums, int l, int r){
        if(l==r)
            return l;
        int mid = (l+r)/2;
        if(nums[mid]>nums[mid+1]){
            return helper(nums, mid+1, r);
        }
        else{
            return helper(nums, l, mid);
        }
    }

 

posted on 2022-01-04 05:53  阳光明媚的菲越  阅读(20)  评论(0编辑  收藏  举报