题解 | #金字塔数组#

金字塔数组

http://www.nowcoder.com/practice/c45c060453324a0aa2745c62a2bd1a27

金字塔数组

描述
给定一个长度为n的数组num,数组开始时呈现递增趋势的,到了某一点之后,数组中的值呈现递减趋势,符合这样先增后减规律的数组定义为金字塔数组,求整个num数组中找出长度最长的金字塔数组,如果金字塔数组不存在,请输出0
示例
输入:4,[1,2,3,1]
返回:4
示例
输入:5,[1,5,3,3,1]
返回:3

方法二

思路分析

    本题我一开始想到了接雨水问题,接雨水问题是根据每一位置左右两侧的最高点计算该位置可以承受的雨水,根据金字塔数组的定义:数组开始时呈现递增趋势的,到了某一点之后,数组中的值呈现递减趋势,符合这样先增后减规律的数组,因此在计算金字塔数组的长度,也就是说找到一条曲线(将数组抽象为一条曲线)的所有波谷(每一子序列的最小值),根据波谷即可计算当前金字塔数组的长度。需要注意的是一开始的位置和最后的位置也可能就是波谷,因此需要单独对这两个位置判断,具体过程如下:
  • 如果num[1]>=num[0],那么开始位置为波谷,进行记录
  • 在中间位置上,如果num[i]<=num[i-1]&num[i]<=num[i+1],那么记录i为波谷
  • 结束位置,如果num[n-1]<=num[n-2],那么记录结束位置为波谷
  • 最后将波谷之间的长度进行计算,找到最长的金字塔数组长度

图解

根据给定数组画出折线图,可以很清楚的找到波谷点,然后得到金字塔数组的长度。


核心代码

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param n int 
     * @param num intvector 
     * @return int
     */
    int getMaxLength(int n, vector<int>& num) {
        // write code here
        vector<int> temp;
        if(n<1) return 0;
        //首先判断第一个位置是否为最低点
        if(num[0]<=num[1]) temp.push_back(0);
        for(int i=1;i<n-1;i++)
        {
            if(num[i]<=num[i-1]&&num[i]<=num[i+1])
            {
                temp.push_back(i);//记录每一个子段最低点
            }
        }
        if(num[n-1]<=num[n-2]) temp.push_back(n-1);//判断最后位置是否为子段最低
        int max_length=0;
        for(int i=1;i<temp.size();i++)
        {
            max_length=max(max_length,temp[i]-temp[i-1]+1);//两个相邻低点之间即为所求数组长
        }
        return max_length;
        
    }
};

复杂度分析

  • 时间复杂度:时间主要是开销在寻找所有符合条件的波谷点,以及计算波谷点之间的长度,因此时间复杂度为$O(n)$
  • 空间复杂度:需要设置一个存放波谷点的数组,因此空间复杂度最大为$O(n)$

方法二

思路分析

方法二是对方法一的进一步优化,由于题目只需要输出金字塔数组的长度,因此无需使用额外的数组存***谷位置元素,只需要一个变量记录上一个波谷的位置,再找到当前波谷位置时,即可计算出当前金字塔数组的长度,从而节省内存空间。

核心代码

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param n int 
     * @param num intvector 
     * @return int
     */
    int getMaxLength(int n, vector<int>& num) {
        // write code here
        if(n<1) return 0;
        int min_index;//记录每一个子段最低点的位置
        int max_length=0;
        //首先判断第一个位置是否为最低点
        if(num[0]<=num[1]) 
        {
            min_index=0;
        }
        for(int i=1;i<n-1;i++)
        {
            if(num[i]<=num[i-1]&&num[i]<=num[i+1])
            {
                max_length=max(max_length,i-min_index+1);
                min_index=i;//令min_index表示当前波谷的上一波谷位置
            }
        }
        if(num[n-1]<=num[n-2]) //判断最后位置是否为子段最低
        {
           max_length=max(max_length,n-1-min_index+1);//如果存在最后一个金字塔数组,将其比较
        }
        return max_length;
        
    }
};

复杂度分析
  • 时间复杂度:该方法的时间复杂度与方法一相同,都是$O(n)$,不过只存在一次循环,要小一些
  • 空间复杂度:空间复杂度相比于方法一减小了,没有设置专门的数组存***谷位置,设置了一个变量存储距离本次波谷最近的波谷位置,因此总的空间复杂度为$O(1)$

全部评论

相关推荐

点赞 评论 收藏
分享
11-09 14:54
已编辑
华南农业大学 产品经理
大拿老师:这个简历,连手机号码和照片都没打码,那为什么关键要素求职职位就不写呢? 从上往下看,都没看出自己到底是产品经理的简历,还是电子硬件的简历? 这是一个大问题,当然,更大的问题是实习经历的描述是不对的 不要只是去写实习流程,陈平,怎么去开会?怎么去讨论? 面试问的是你的产品功能点,是怎么设计的?也就是要写项目的亮点,有什么功能?这个功能有什么难处?怎么去解决的? 实习流程大家都一样,没什么优势,也没有提问点,没有提问,你就不得分 另外,你要明确你投的是什么职位,如果投的是产品职位,你的项目经历写的全都是跟产品无关的,那你的简历就没用 你的面试官必然是一个资深的产品经理,他不会去问那些计算机类的编程项目 所以这种四不像的简历,在校招是大忌
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务