题解 | #栈和排序#

栈和排序

http://www.nowcoder.com/practice/95cb356556cf430f912e7bdf1bc2ec8f

栈和排序

描述

给你一个 1 到 n 的排列和一个栈,并按照排列顺序入栈,你要在不打乱入栈顺序的情况下,仅利用入栈和出栈两种操作,输出字典序最大的出栈序列。排列:指 1 到 n 每个数字出现且仅出现一次
示例
输入:[2,1,5,3,4]
返回值:[5,4,3,1,2]
说明:
操作       栈     结果
2 入栈;[2]       []
1 入栈;[2\1]     []
5 入栈;[2\1\5]   []
5 出栈;[2\1]     [5]
3 入栈;[2\1\3]   [5]
4 入栈;[2\1\3\4] [5]
4 出栈;[2\1\3]   [5,4]
3 出栈;[2\1]     [5,4,3]
1 出栈;[2]       [5,4,3,1]
2 出栈;[]        [5,4,3,1,2]


方法一

思路分析

本题需要通过示例说明进行分析,进而得到一般性的结论,分析如下:
  • 首先先将数入栈,栈顶元素为2,比较发现未入栈的元素中还有比2更大的数,因此2不能作为最大字典序中的开始元素;
  • 继续对后面数组中的元素入栈,1入栈,相同的方法与后面数组中的元素比较,比较发现未入栈的元素中还有比2更大的数
  • 继续对后面数组中的元素入栈,5入栈,相同的方法与后面数组中的元素比较,比较发现未入栈的元素中没有比5更大的数,因此5出栈,作为最大字典序中的开始元素
  • 相同的办法对数组中的元素进行操作,此时4入栈,比较发现未入栈的元素中没有比4更大的数,4出栈
  • 数组中的元素已经全部入过栈,因此根据先进后出的方法输出栈中元素,分别为3,1,2出栈
  • 总的字典序即为[5,4,3,1,2],操作完成,输出字典序最大的出栈序列
因此我们可以得到一般性的结论:
  • 设置一个数组temp记录给定数组a从当前位置的下一位置出发到结束位置的最大元素;
  • 给定数组中的元素一次入栈,
  • 栈顶元素与给定数组中为入栈的元素进行比较,即与temp[i]比较,如果栈顶元素更大,说明该栈顶元素应该出栈,即在最大字典序中的位置;
  • 继续上述步骤,直到给定数组中的元素都进行过入栈操作,此时如果栈中元素不为空,则将栈中元素弹出,构成完整的序列,即为字典序最大的序列。
在具体求解temp数组时我们需要每次找到该元素之后的数组中的最大值,从而填充temp数组

图解

核心代码

class Solution {
public:
    /**
     * 栈排序
     * @param a int整型一维数组 描述入栈顺序
     * @param aLen int a数组长度
     * @return int整型vector
     */
    vector<int> solve(int* a, int aLen) {
        // write code here
        vector<int>temp(aLen,a[aLen-1]);
        stack<int> s;
        vector<int>ans;
        for(int i=0;i<=aLen-2;i++)
        {
            temp[i]=a[i];
            for(int j=i+1;j<=aLen-1;j++)
            {
                if(temp[i]<a[j])
                    temp[i]=a[j];
            }
           
            
        }
        for(int i = 0; i < aLen; i++) 
        {
            s.push(a[i]);//数组元素入栈
            while(!s.empty() && s.top() > temp[i+1])//栈顶元素与temp[i+1]元素比较
            {
              ans.push_back(s.top());//如果栈顶元素较大,出栈
              s.pop();
            }
        }
        while(!s.empty())//所有的数入栈后,最后将栈中输出
        {
    	  ans.push_back(s.top());
    	  s.pop();
        }
        return ans;
    }
};
复杂度分析
  • 时间复杂度:首先需要填充temp数组,从开始位置的下一个位置出发到结束位置寻找最大值,所需时间复杂度为$O(n+n-1+n-2+n-3+...+2+1)$,时间复杂度为$O(n^2)$,接着需要遍历一次数组,所需时间复杂度为$O(n)$,因此总的时间复杂度为$O(n^2)$
  • 空间复杂度:借助于一个数组用于存放未入栈元素的最大值,设置一个栈空间,大小为n,空间复杂度为$O(n)$

方法二

思路分析

      方法二对方法一中temp数组的求解进行优化,这里采用动态规划的思想,从后往前遍历数组,那么temp[i]=max{temp[i+1],a[i]},此时求解temp数组的时间复杂度降低为$O(n)$

图解

核心代码

class Solution {
public:
    /**
     * 栈排序
     * @param a int整型一维数组 描述入栈顺序
     * @param aLen int a数组长度
     * @return int整型vector
     */
    vector<int> solve(int* a, int aLen) {
        // write code here
        vector<int>temp(aLen,a[aLen-1]);
        stack<int> s;
        vector<int>ans;
        for(int i=aLen-2;i>=0;i--)
        {
            temp[i]=max(temp[i+1],a[i]);
        }
        for(int i = 0; i < aLen; i++) 
        {
           s.push(a[i]);
            while(!s.empty() && s.top() > temp[i+1])
            {
              ans.push_back(s.top());
              s.pop();
            }
        }
        while(!s.empty())
        {
    	  ans.push_back(s.top());
    	  s.pop();
        }
        return ans;
    }
};
复杂度分析
  • 时间复杂度:首先循环遍历一次数组a求出temp数组,利用了动态规划的思想,从后往前,时间复杂度为$O(n)$,接着对数组元素操作入栈出栈,时间复杂度为$O(n)$,因此总的时间复杂度为$O(n)$
  • 空间复杂度:需要额外设置一个temp数组存放数组a中每个位置的下一位置到结束位置的最大值,设置一个栈空间,大小为n,因此时间复杂度为$O(n)$


方法三

思路分析

接着我们使用另一种方法,注意到给定数组是1 到 n 的排列,也就是说,当前除栈顶元素外,其余未入栈元素的最大值其实是可以确定的:记录出栈元素,那么就可以计算出未入栈元素的最大值,之后将栈中元素全部输出。

核心代码

class Solution {
public:
    /**
     * 栈排序
     * @param a int整型一维数组 描述入栈顺序
     * @param aLen int a数组长度
     * @return int整型vector
     */
    vector<int> solve(int* a, int aLen) {
        // write code here
        //vector<int>temp(aLen,a[aLen-1]);
        stack<int> s;
        vector<int>ans;
        int index=aLen;
        vector<int>temp(aLen+1,0);
        for(int i = 0; i < aLen; i++) 
        {
            s.push(a[i]);//数组元素入栈
            temp[a[i]]=1;
            while(index>0&&temp[index]==1) index--;//当前未入栈元素的最大值
            while(!s.empty()&&s.top()>index)//栈顶元素与未入栈元素的最大值比较
            {
              ans.push_back(s.top());//如果栈顶元素较大,出栈
              s.pop();
            }
        }
        return ans;
    }
};
复杂度分析
  • 时间复杂度:对数组元素操作入栈出栈,时间复杂度为$O(n)$
  • 空间复杂度:需要额外设置一个temp数组存放数组a中每个位置是否出栈,设置一个栈空间,大小为n,因此时间复杂度为$O(n)$
全部评论

相关推荐

评论
1
收藏
分享

创作者周榜

更多
正在热议
更多
# 长得好看会提高面试通过率吗? #
3209次浏览 43人参与
# HR最不可信的一句话是__ #
1021次浏览 32人参与
# 巨人网络春招 #
11484次浏览 224人参与
# 春招至今,你的战绩如何? #
14766次浏览 137人参与
# AI面会问哪些问题? #
893次浏览 22人参与
# 你的实习产出是真实的还是包装的? #
2722次浏览 52人参与
# MiniMax求职进展汇总 #
24901次浏览 321人参与
# 沪漂/北漂你觉得哪个更苦? #
1235次浏览 38人参与
# 你做过最难的笔试是哪家公司 #
1131次浏览 20人参与
# AI时代,哪个岗位还有“活路” #
2684次浏览 49人参与
# XX请雇我工作 #
51147次浏览 171人参与
# 军工所铁饭碗 vs 互联网高薪资,你会选谁 #
7966次浏览 43人参与
# 简历第一个项目做什么 #
32073次浏览 357人参与
# 简历中的项目经历要怎么写? #
310908次浏览 4257人参与
# 不考虑薪资和职业,你最想做什么工作呢? #
152832次浏览 889人参与
# 当下环境,你会继续卷互联网,还是看其他行业机会 #
187556次浏览 1123人参与
# AI时代,哪些岗位最容易被淘汰 #
64539次浏览 864人参与
# 如果重来一次你还会读研吗 #
229974次浏览 2011人参与
# 投格力的你,拿到offer了吗? #
178254次浏览 891人参与
# 你怎么看待AI面试 #
180654次浏览 1296人参与
# 正在春招的你,也参与了去年秋招吗? #
364172次浏览 2641人参与
# 腾讯音乐求职进展汇总 #
160822次浏览 1114人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务