牛客 吐泡泡 (栈和队列)

题目描述
小鱼儿吐泡泡,嘟嘟嘟冒出来。小鱼儿会吐出两种泡泡:大泡泡"O",小泡泡"o"。
两个相邻的小泡泡会融成一个大泡泡,两个相邻的大泡泡会爆掉。
(是的你没看错,小气泡和大气泡不会产生任何变化的,原因我也不知道。)
例如:ooOOoooO经过一段时间以后会变成oO。

输入描述:
数据有多组,处理到文件结束。
每组输入包含一行仅有’O’与’o’组成的字符串。
输出描述:
每组输出仅包含一行,输出一行字符串代表小鱼儿吐出的泡泡经过融合以后所剩余的泡泡。

输入
ooOOoooO

输出
oO

说明
自左到右进行合并

备注:
对于100%的数据,
字符串的长度不超过100。

题目分析:考虑用栈去做,但是其中情况有很多,我刚开始做的时候就是没搞清楚大关系与小关系的位置,最后输出的时候,记得如果用的是栈那就反向输出,因为栈的性质就是先进后出。可以开一个新的数组储存正向的,然后反向遍历输出即可。

#include <bits/stdc++.h>
using namespace std;
char a[1010], b[1010];
stack<char> s;
int main()
{
   
    while (~scanf("%s", a))
    {
   
        int la = strlen(a);
        for (int i = 0; i < la; ++i)
        {
   
            if (s.empty()) //如果为空直接入栈无法匹配
                s.push(a[i]);
            else if (s.top() == a[i])
            {
   
                if (s.top() == 'o') //同为小气泡
                {
   
                    s.pop();
                    if (s.size() && s.top() == 'O') //融合为大气泡时如果前面存在大气泡,出栈
                        s.pop();
                    else
                        s.push('O'); //否则入栈两个小气泡合成的大气泡
                }
                else if (s.top() == 'O') //如果相同,又是大气泡那直接出栈
                    s.pop();
            }
            else
                s.push(a[i]);
        }
        int h = 0;
        while (!s.empty())
        {
   
            b[++h] = s.top();
            s.pop();
        }
        for (int i = h; i >= 1; --i)
            putchar(b[i]);
        puts("");
    }
    return 0;
}

队列

#include <bits/stdc++.h>
using namespace std;
deque<char> st;
string str;
int main()
{
   
    while (cin >> str)
    {
   
        for (int i = 0; str[i]; ++i)
        {
   
            char c = str[i];
            if (st.empty() || st.back() != c)
                st.push_back(c);
            else
            {
   
                if (c == 'o')
                {
   
                    st.pop_back();
                    if (!st.empty() && st.back() == 'O')
                        st.pop_back();
                    else
                        st.push_back('O');
                }
                else
                    st.pop_back();
            }
        }
        while (!st.empty())
        {
   
            cout << st.front();
            st.pop_front();
        }
        puts("");
    }
}

附加题

动态数组模拟,有点像约瑟夫环
题目描述
编号为1、2、3、…、n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。从指定编号 为1的人开始,按顺时针方向自1开始报数,报到指定值m时停止报数,报第m的人出列,并将他的密码作 为新的m值,从他在顺时针方向的下一个人开始,重新从1开始报数,如此类推,直至所有的人全部出列 为止。输入n(n<=1000),m(m<=30000)及密码值(<=10000),试设计一个程序求出列顺序 。
输入
有二行,第一行,N和M,第二行,N个小于等于10000的密码值,中间用空格隔开。
输出
只有一行,就是出列的顺序,编号间以空格隔开。
样例输入
6 7
1 4 2 8 5 7

样例输出
1 2 6 3 5 4

AC代码

#include <bits/stdc++.h>
using namespace std;
int a[1010], vis[1010];
vector<int> q;
int n, m, cnt;
int main()
{
   
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i)
        scanf("%d", &a[i]);
    for (int i = 1; i <= n; ++i)
    {
   
        if (q.size() == n - 1) //如果还剩最后一个人
        {
   
            for (int j = 1; j <= n; ++j) //直接遍历看看还有谁没有标记过,如果没有那就是他
                if (!vis[j])
                    q.push_back(j);
            break;//这个break很有必要,因为这是一个无限循环,一定要有一个终点,终点就是最后一个人出栈
        }
        if (!vis[i]) //如果当前的人没有被标记
        {
   
            ++cnt;        //就一直加
            if (cnt == m) //如果等于预期的数字那就要进行一段操作
            {
   
                m = a[i];       //首先就要重新更新m的值
                q.push_back(i); //然后把被点到的人放入数组
                vis[i] = 1;     //标记此人,相当于删除去此人
                cnt = 0;        //清空,开始下一次循环
            }
        }
        if (i == n) //因为模拟的是圆桌,人与人形成一个环,所以如果到了最后一个编号那就重新开始
            i = 0;
    }
    for (int i = 0; i < q.size(); ++i)//按照题目的意思输出即可
    {
   
        if (i == 0)
            printf("%d", q[i]);
        else
            printf(" %d", q[i]);
    }
}
让梦想照进现实的唯一方法,就是走好脚下的路,静待天边梦想的阳光洒下。
全部评论

相关推荐

Java抽象带篮子:实习经历可以包装下,可以看看我的包装帖子
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务