题解 | #单调栈#

单调栈

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

单调栈

问题描述:给定一个可能含有重复值的数组 arr,找到每一个 i 位置左边和右边离 i 位置最近且值比 arr[i] 小的位置。返回所有位置相应的信息。位置信息包括:两个数字 L 和 R,如果不存在,则值为 -1,下标从 0 开始。
示例
输入:[3,4,1,5,6,2,7]
返回值:[[-1,2],[0,2],[-1,-1],[2,5],[3,5],[2,-1],[5,-1]]

 方法一

思路分析

       首先介绍什么是单调栈 ,就是在栈的先进后出基础之上额外添加一个特性: 从栈顶到栈底的元素是严格递增或者递减。 对于单调递增栈,若当前进栈元素为 $e$,从栈顶开始遍历元素,把小于 $e $或者等于 $e$ 的元素弹出栈,直到遇到一个大于$ e$ 的元素或者栈为空为止,然后再把$ e$ 压入栈中。对于本题来说要想找到每一个 $i $位置左边离$ i $位置最近且值比 $arr[i] $小的位置,需要构造单调递增栈,步骤如下:
  • 设置一个栈$stk$,设置二维数组$array$,其中$array[i][0]$表示左边位置离$ i$ 位置最近且值比 $arr[i] $小的位置,$array[i][1]$表示右边位置离$i$位置最近
  • 从开始元素出发,从左往右,如果栈不为空,且该元素大于栈顶元素,则$array[i][0]$为栈顶元素位置,而后直接将其压入栈中;
  • 如果该元素小于栈顶元素,则将栈顶元素移除,继续比较,直到找到栈顶元素小于该元素的情况,此时如果栈为空,则该元素的$array[i][0]=-1$,否则$array[i][0]$为栈顶元素位置,最后该元素压入栈中
对于本题来说要想找到每一个$ i$位置右边离$ i $位置最近且值比 $arr[i] $小的位置,需要构造单调递增栈,步骤如下:
  • 设置一个栈$stk$,$array[i][1]$表示右边位置离$i$位置最近最近且值比 $arr[i] $小的位置
  • 从最后的元素出发,从右往左,如果栈不为空,且该元素大于栈顶元素,则$array[i][1]$为栈顶元素位置,而后直接将其压入栈中;
  • 如果该元素小于栈顶元素,则将栈顶元素移除,继续比较,直到找到栈顶元素小于该元素的情况,此时如果栈为空,则该元素的$array[i][1]=-1$,否则$array[i][1]$为栈顶元素位置,最后该元素压入栈中

图解





C++核心代码

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param nums intvector 
     * @return intvector<vector<>>
     */
    vector<vector<int> > foundMonotoneStack(vector<int>& nums) {
        // write code here
        int top = -1;
        int n=nums.size();
        stack<int> stk;
        vector<vector<int>> array(n);//定义一个5*2的数组存放结果
        for (int i = 0; i < array.size(); i++)
              array[i].resize(2);
        for ( int i = 0; i < n; i++ ) 
        {
        while ( !stk.empty() && nums[stk.top()] >= nums[i] ) stk.pop();//保证栈顶元素是小于待入栈的
        if ( stk.empty() ) array[i][0] = -1;//栈为空,说明该位置元素左侧没有比它小的数
        else array[i][0] = stk.top();//如果栈不为空,则左侧比其值小的元素位置距离最近
        stk.push(i);//该元素入栈
        }
        while(!stk.empty()) stk.pop();//清空栈
        for ( int i = n - 1; i >= 0; i-- ) 
        {
        while (!stk.empty() && nums[stk.top()] >= nums[i] ) stk.pop();
        if ( stk.empty() ) array[i][1] = -1;//栈为空,说明该位置元素右侧没有比它小的数
        else array[i][1] = stk.top();//如果栈不为空,则右侧比其值小的元素位置距离最近
        stk.push(i);//该元素入栈
        }
        return array;
    }
};

复杂度分析

  • 时间复杂度:两次循环,每次循环的复杂度为$O(n)$,循环内部存在入栈出栈的操作,要想找到每一个 i 位置左边离 $i $位置最近且值比$ arr[i] $小的位置,如果数组是逆序的,那么操作的次数为在寻找因此总的时间复杂度为$O(n^2)$
  • 空间复杂度:借助于一个二维数组以及一个栈,空间复杂度为$O(n)$

方法二

思路分析

     如果说方法一是根据题目所想到的,那么我们可以直接想到的方法其实是暴力搜索的办法,首先从开始元素出发遍历,从右往左循环找到该元素左侧第一个小于该元素的位置,从左往右找到第一个小于该元素的位置,如果没有则记为-1。

C++核心代码

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param nums intvector 
     * @return intvector<vector<>>
     */
    vector<vector<int> > foundMonotoneStack(vector<int>& nums) {
        // write code here
        int n=nums.size();
        vector<vector<int>> array(n);//定义一个5*2的数组存放结果
        for (int i = 0; i < array.size(); i++)
              array[i].resize(2);
        for(int i=0;i<n;i++)
        {
            array[i][0]=-1;
            array[i][1]=-1;
            for(int j=0;j<i;j++)
            {
                if(nums[j]<nums[i])//左侧离 i 位置最近且值比 arr[i] 小的位置
                    array[i][0]=j;
            }
            for(int j=n-1;j>i;j--)
            {
                if(nums[j]<nums[i])//右侧离 i 位置最近且值比 arr[i] 小的位置
                    array[i][1]=j;
            }
        }
        return array;
    }
};

复杂度分析

  • 时间复杂度:两层循环,外层循环为$n$,内层循环最大为$n$,因此时间复杂度为$O(n^2)$
  • 空间复杂度:  设置了一个的辅助数组,因此空间复杂度为$O(n)$

全部评论

相关推荐

老板加个卤鸡蛋:HR看了以为来卧底来了
点赞 评论 收藏
分享
评论
6
3
分享

创作者周榜

更多
正在热议
更多
# 长得好看会提高面试通过率吗? #
4018次浏览 46人参与
# 离家近房租贵VS离家远但房租低,怎么选 #
16907次浏览 137人参与
# 米连集团26产品管培生项目 #
7308次浏览 226人参与
# 春招至今,你的战绩如何? #
15816次浏览 145人参与
# 你的实习产出是真实的还是包装的? #
3098次浏览 53人参与
# 沪漂/北漂你觉得哪个更苦? #
1553次浏览 41人参与
# 巨人网络春招 #
11527次浏览 224人参与
# HR最不可信的一句话是__ #
1091次浏览 32人参与
# AI面会问哪些问题? #
946次浏览 23人参与
# 你做过最难的笔试是哪家公司 #
1247次浏览 22人参与
# AI时代,哪个岗位还有“活路” #
2853次浏览 51人参与
# 不考虑薪资和职业,你最想做什么工作呢? #
152905次浏览 889人参与
# 军工所铁饭碗 vs 互联网高薪资,你会选谁 #
8021次浏览 43人参与
# XX请雇我工作 #
51155次浏览 171人参与
# 简历第一个项目做什么 #
32148次浏览 361人参与
# 简历中的项目经历要怎么写? #
311051次浏览 4265人参与
# 投格力的你,拿到offer了吗? #
178339次浏览 891人参与
# 你最满意的offer薪资是哪家公司? #
76981次浏览 375人参与
# 当下环境,你会继续卷互联网,还是看其他行业机会 #
187605次浏览 1123人参与
# AI时代,哪些岗位最容易被淘汰 #
64760次浏览 890人参与
# 如果重来一次你还会读研吗 #
230018次浏览 2011人参与
# 正在春招的你,也参与了去年秋招吗? #
364353次浏览 2642人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务