【栈】2020牛客寒假算法基础集训营6 G题

2020牛客寒假算法基础集训营6 G题 【括号序列】
一道典型的栈的题目
为什么收录进来,因为感觉自己不够熟悉,22分钟写得太慢了…

链接:https://ac.nowcoder.com/acm/contest/3007/G
来源:牛客网

题目描述
合法括号序列的定义是:
1.空序列是合法括号序列
2.如果 S 是一个合法括号序列,那么(S)是合法括号序列
3.如果 A 和 B 都是合法括号序列,那么 AB 是一个合法括号序列
现在给定一个括号序列,求最少删去几个括号能得到一个合法的括号序列
输入包含 T 组数据,每组数据中,设括号序列的长度为 N
1≤T,ΣN≤1,000,000
(由于空串是合法的括号序列,所以答案可以是N

输入描述:
第一行一个数字 T
接下来 T 组数据共 2T 行,每组数据第一行是 N
第二行则是一个长度为 N 的括号序列

输出描述:
T 行 T 个数字,表示输入的括号序列最少删去几个括号能得到一个合法的括号序列

示例
输入
2
6
())(()
9
()(()()))
输出
复制
2
1

比赛时的想法:
水题,一定要快点a掉。
无奈手速和脑速不够。。

解题思路:
遇左括号,直接入栈;
遇右括号,则判断栈里是否为空
若空,则此右括号必多余,cnt++;
否则,将栈顶的左括号取出;
最后,for循环结束之后,栈里可能有多余的左括号,所以直接加size。

代码段:

while(t--){
        while(!ss.empty()) ss.pop();
        int cnt=0;
        read(n);
        cin>>s;
        for(int i=0;i<n;i++){
            if(s[i]=='('){
                ss.push(s[i]);
            }
            if(s[i]==')'){
                if(ss.empty()){
                    cnt++;
                }else{
                    ss.pop();
                }
            }
        }
        cnt+=ss.size();
        printf("%d\n",cnt);
    }

注意事项:
多组输入时,勿忘将栈给清空。

大佬代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
 
using namespace std;
const int N = 1000050;
 
int T, n, l, r, sum, ans; char s[N];
int main()
{
    int i, j, k;
    scanf("%d", &T);
    while(T --){
        scanf("%d", &n);
        scanf("%s", s + 1);
        l = r = sum = ans = 0;
        for(i = 1; i <= n; i ++){
            if(s[i] == '(')
                l ++, sum ++;
            else if(sum > 0)
                r ++, sum --;
            else ans ++;
        }
        printf("%d\n", ans + l - r);
    }
     
    return 0;
}

理解思路:
没有使用栈;
定义了l,r,sum,ans;
如遇左括号,l++,sum++;
如遇右括号
若sum为正,则r++,sum–;
否则,必匹配不了,直接ans++;
运用了前缀和思想。

//借鉴代码用于学习总结,如有侵权务必联系我。

发布了16 篇原创文章 · 获赞 0 · 访问量 115

猜你喜欢

转载自blog.csdn.net/weixin_44745441/article/details/104366371