zoukankan      html  css  js  c++  java
  • leetcode 162. 寻找峰值(二分)

    在这里插入图片描述
    转自https://blog.csdn.net/qq_41231926/article/details/86369916
    在这里插入图片描述

    这个博客说的很清楚。

    首先第一次拿到题的时候是给了这样的条件,给一个序列a,序列a[0]<a[1] && a[n-1]<a[n-2]

    序列中间是无序的,求某个位置i,使得a[i]>a[i+1]&&a[i]>a[i-1]

    要用log级别的方法。

    首先对于这样一个问题,一般想着肯定是暴力跑一遍,得到第一个符合条件的i就输出即可。

    然后这里说要log级别的方法,那么想到的只有二分或者三分,而序列又是无序的,就想不出怎么分了。

    首先可以注意到的是该题要找峰值,而且是连续三个数中的峰值。如何二分是个问题。注意到左右两端已经给出了趋势,即是左边上升,右边下降。

    而我们可以采取这样的策略,二分取得mid后,若其于左边的值形成下降趋势,那么于最左端相连之后,一定会形成一个峰值,右端也是一样的,所以我们尽量选取mid<mid+1或mid<mid-1的方向继续进行二分。

    不用在意mid与其相邻值对于最左最右端的大小,因为无论大小,二者相连后都会形成峰值,因为这两个值旁边都有一个小于自己的数。

    即使我们不知道该峰值是谁,但是可以明确的是,因为两端有这样的趋势,那么不断缩小距离,就离峰值越来越近

    代码如下:

    class Solution {
    public:
        int findPeakElement(vector<int>& nums) {
            int l=0,r=nums.size()-1;
            if(r<=2)
            {
                if(r==0)return 0;
                else if(r==1)return nums[0]>nums[1]?0:1;
                else
                {
                    int ans=0;
                    if(nums[0]>nums[1])ans=0;
                    else ans=1;
                    if(nums[ans]>nums[2])return ans;
                    else return 2;
                }
            }
            while(l<r)
            {
                int mid=(l+r)>>1;
                if(mid==0)return nums[0]>nums[1]?0:1;
                if(nums[mid]>nums[mid+1]&&nums[mid]>nums[mid-1]) return mid;
                else if(nums[mid]>nums[mid+1])r=mid-1;
                else l=mid+1;
            }
            return l;
        }
    };
    
  • 相关阅读:
    最短路--floyd算法模板
    poj2367 拓扑序
    poj1094 拓扑序
    hdu3231 拓扑序
    hdu1811 并查集+拓扑序
    hdu3342 拓扑序
    hdu2647 拓扑序
    hdu1285 拓扑序
    UVA10305 拓扑序
    $.proxy
  • 原文地址:https://www.cnblogs.com/kuronekonano/p/11135650.html
Copyright © 2011-2022 走看看