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++;
运用了前缀和思想。
//借鉴代码用于学习总结,如有侵权务必联系我。