一起刷算法 #二分 # 02

题目

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

解题思路

这道题可以用一种逼近的思想去做,去找到这个峰值。
先思考一个问题,二分法的核心是什么?个人觉得,二分的核心就是决定丢弃哪一部分,左边还是右边应该被丢弃呢?这个决定如何做?那就要看具体的数据特征,例如这道题中的“峰值”这个概念。

对于峰值,他有这样一个特点,如果if(nums[mid] < nums[mid + 1]),即目前的mid位置值要是小于它左边的值,说明峰值(其中之一)肯定在mid位置的左边,
那么这个时候我们就可以决定丢弃右边的数,如何丢弃:low = mid + 1,将左边界往右边缩。
相应的,如果mid位置值大于它左边的值呢,那么就hi值往右边缩,hi = mid

关键来了,为什么不是hi = mid -1;
这是因为在一般二分中,我们有一句if(nums[mid] == target)break;即mid位置的值是被check到了的。所以可以直接加减1跳过它。但是这里没有遍历到mid的值,所有用hi = mid
而最后返回low就是因为low = mid + 1,即mid位置是目前最大值的位置。

那么这个算法整体就是什么效果呢?
看mid,决定丢弃哪边,往左边走还能更大的话就丢了右边,去左边找峰值。要是往左边走反而变小了,那就丢了左边,在右边去寻找。

左右就像分岔口的两个方向,要到达顶峰,你只需要不断地选择上升的方向就行。

这道题和这道题https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array/
有异曲同工之妙

代码

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

posted @ 2021-12-23 16:37  岚鱼yu  阅读(26)  评论(0)    收藏  举报