题解 | #寻找峰值#

寻找峰值

https://www.nowcoder.com/practice/fcf87540c4f347bcb4cf720b5b350c76

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param nums int整型vector 
     * @return int整型
     */
    int findPeakElement(vector<int>& nums) {
        // write code here
        //只要向高的地方收缩一定可以找到一个峰值
        int left=0;
        int right=nums.size()-1;
        
        while(left<right)
        {
            int mid=left+(right-left)/2;
            if(nums[mid]>nums[mid+1])//左边一定有峰值,并且可能是mid
            {
                right=mid;
            }
            else 
            {
                left=mid+1;
            }
        }

        return right;
    }
};

1.思路:对于一个数组,如果认为它的两端(下标为-1,size()两处)是最低的,那么这个数组一定存在峰值;因此nums一定存在峰值。

取nums的中点下标mid,如果nums[mid]>nums[mid+1],那么mid的左区域(含mid)一定存在峰值(因为左区域两端是最低的)将

这个区域作为新的"nums数组";如果nums[mid]<nums[mid+1],那么mid的右区域(不含mid)一定存在峰值(因为右区域两端是最低的)将这个区域作为新的"nums数组"执行算法,这样"nums数组"就会向存在峰值的方向不断缩小,直到可以选出峰值

2.为什么返回right:

在跳出循环前的最后一步,left和right可能满足关系left+1=right或者left+2=right,

先分析left+1=right的情况

若left+1=right,计算可得:mid=left;

而我们知道峰值一定是nums[left]和nums[right]中的较大者,

假设nums[left]较大,那么,区间向左收缩,right=mid=left=峰值下标,此时返回right;

假设nums[left]较小,那么,区间向右收缩,right不变,此时返回right也是可以的;

left+2=right时

mid=left+1;

若nums[mid]<nums[right];那么,区间向右收缩,right不变,此时返回right也是可以的;

若nums[mid]>nums[right];,区间向左收缩,归结为情况left+1=right;

即:从最后一步分析可以看出,在right=left时退出循环是合理的,可以直接返回right(或者是left)

全部评论

相关推荐

点赞 评论 收藏
分享
流浪的神仙:无恶意,算法一般好像都得9硕才能干算法太卷啦
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务