【18715 出栈序列】 模拟 贪心+双指针

Description
一种简洁的栈定义方法如下
int st[1000],top=0;//以top作为栈顶指针,top==0为空栈
st[top++]=x;//把x入栈,栈顶指针+1
top–;//出栈
现在有一个1-n的排列,入栈序列已知,请给出字典序最大的出栈序列。

输入格式
第一行一个整数n。(1<=n<=100)
第二行n个整数,数据确保为1-n的排列。

输出格式
输出n个整数,既字典序最大的出栈序列。

输入样例
5
1 2 4 5 3

输出样例
5 4 3 2 1

题意就是说给你一个入栈的顺序,你可以进来一个pop掉一个,也可以进来多个后pop掉一个,问最后的最大字典序的出栈序列是什么?

主要思路(贪心):

既然说是贪心了,就是说我每次取出来的元素都应该是在满足出栈规则的条件下,能取到的最大值。
1.我用一个R指针遍历一遍未进栈的元素,找出他的最大值,然后对比L,L指向的是当前栈顶元素,R和当前栈顶元素对比。
2.如果R比当前栈顶元素(L)要大,那就把L-R的元素统统压进栈后,pop掉R指向的元素,因为它是现在能遍历到的最大的元素。此时更新L,栈顶元素位置变成L = R-1
3.如果栈顶元素更大的话,那就把栈顶元素pop掉,R的位置不改变(相当于现在还不需要把L-R元素压进栈)。这个时候L = L-1 。
4.一些细节要注意一下,因为我是把每次出栈的元素置为-1,所以L, R更新的时候,不是简单的L = R-1或L = L-1,他的意思是R或L左边第一个不为-1的元素当做栈顶(-1的已经不在了嘛)。
大概思路就是这样,一些更详细的细节得写了代码才知道。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
int a[105];
int main()
{
    int n;
    cin>>n;
    int L=0, R=1;           //双指针,先将左指针指向第0号元素,R指向第1号元素
    for(int i=1;i<=n;i++)       //读入
    {
        cin>>a[i];
    }
    int cnt = 0;        //计数器
    while(cnt<n)            //循环出口是n个数都得到输出
    {
        for(int i=R;i<=n;i++)       //先找到右边能找到的最大值,即是贪心思想
        {
            if(a[i]>a[R])
            R = i;
        }

        if(L>=1&&a[L]>a[R])         //这个时候L代表选这个元素之前的栈顶元素下标,对比,我要直接pop更优还是压进多个知道R进来后pop掉更优?
        {
            if(cnt!=n-1)        //保险,最后一个数不要空格,直接回车
             cout<<a[L]<<' ';
             else cout<<a[L]<<endl;
              a[L] = -1;            //如果L这个元素更大,选它,然后标记为-1,代表用过了,以后也不会再取到它(每次取最大嘛,都是正整数)
             for(int i = L-1; i>=1;i--)         //然后更新L,往左边找第一次出现的还没用过的元素(就相当于L pop掉后的栈顶元素)
             {
                 if(a[i]!=-1)
                 {
                     L = i;
                     break;
                 }
             }
              cnt++;        //计数++
        }
        else            //如果R指向的更大
        {
            if(cnt!=n-1)
            cout<<a[R]<<' ';
            else  cout<<a[R]<<endl;
            a[R] = -1;
            R++;            //这个时候L,R都要更新,R因为是在还没进栈的元素里面找,所以只能往后移动
            for(int i = R-1; i>=1;i--)      //这时候L更新成Rpop掉之后的栈顶元素
             {
                 if(a[i]!=-1)
                 {
                     L = i;
                     break;
                 }
             }
            cnt++;
        }
    }

    return 0;
}

你可能感兴趣的:(SCAU,贪心,题解,SCAU,贪心,双指针,算法,题解)