SCAU 18715 出栈序列( ★ ★) (408复习随想)

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

        一道不错的考察对栈存取理解运用的题目,要求也很简单,数据规模很小(n<=100),数据唯一,因此算法复杂度不用卡太紧就能过。

        算法原理:对于一条固定的入栈序列,假设是从左到右依次入栈,则第一个出栈元素能自由选择,不难理解,一直push,直到遇到想pop的元素就好。题目要求出栈序列元素满足字典序从大到小排序,那第一个出栈元素是最大的元素就OK。第ii不为1)个出栈元素只能从第i-1个出栈元素的左边第一个未出栈元素以及右边所有未进栈元素中选取,右边的序列选择最大的,与左边比较,max(左,右),记录下标,出栈并标记,然后移动指针到该出栈元素的下标,用循环重复这个过程直至将所有元素出栈。

        算法复杂度:考408一般都要计算自己写的算法的复杂度。由于每个出栈元素都要在上一个出栈元素左扫描右扫描一次,看作n级别,共有n个元素,因此时间复杂度为O(n^2)。算法额外创建3个大小为n+1的数组,因此空间复杂度为O(n)。

代码:

#include <iostream>
//出栈序列

using namespace std;

int getNext(int a[],int maxi,int next,int n,bool b[])
{
    //返回的是下一个出栈的下标
    if(next==0)
    {
        return 0;
    }
    int last,nexti = maxi+1;
    for(int i=maxi-1;i>0;i--)
    {
        if(!b[i])
        {
            last = a[i];
            maxi = i;
            break;
        }
    }
    next = last;
    for(int i=nexti;i<=n;i++)
    {
        if(a[i]>next&&!b[i])
        {
            maxi = i;
            next = a[i];
        }
    }
    return maxi;
}


int main()
{
    int n;
    cin>>n;
    int a[n+1],st[1000];
    bool b[n+1];//标记出栈的元素
    int maxi = 0;
    for(int i=1;i<=n;i++)
    {
        //初始化
        b[i] = false;
        cin>>a[i];
        if(a[i]==n)
        {
            maxi = i;//初始化时就找到最大元素的下标
        }
    }
    for(int top=n;top>0;top--)
    {
        b[maxi] = true;
        st[top] = a[maxi];//出栈,记录序列用st[n]到st[1]
        maxi = getNext(a,maxi,top-1,n,b);
    }
    for(int i=n;i>0;i--)
    {
        cout<<st[i]<<' ';
    }
    return 0;
}

后记:
        n<=100,因此会出现两位数、三位数的情况,但是由于不用将序列拼在一起成一个串,因此,就当它要从大到小输出就好,字典序那里完全是描述有问题,吓唬人。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值