如果通过插入“ +”和“ 1”可以从中得到格式正确的数学表达式,则将带括号的序列称为正确的。
例如,序列 "(())()","()"和 "(()(()))"是正确的,而")(","(()))("和"(()" 不是。
定义重新排序操作:选择括号序列的任意连续子段(子字符串),然后以任意方式对其中的所有字符进行重新排序。
当重新排序的子段的长度为t时,重新排序操作需要耗时t秒。
例如,对于“))((”,他可以选择子字符串“)(”并重新排序“)()(”(此操作将花费2秒)。
不难看出,重新排序操作不会改变左括号和右括号的数量。
现在,LD想花费最少的时间,通过任意次数(可能为零)执行重新排序操作来使括号序列变成正确的。
输入格式:
第一行包含一个整数n(1≤n≤1e6),表示序列的长度;
第二行包含一个长度为n的字符串,仅由字符‘(’和‘)’组成。
输出格式:
输出一个整数,表示使括号序列正确的最小秒数;如果不可能实现,则输出-1。
输入样例:
8
))((())(
输出样例:
6
代码:
#include<stdio.h>
int main()
{
int num; scanf("%d", &num);
char stack[num + 1] = {'0'}; int top = 1, ans = 0; // 栈首元素来一个'0',防止越界读取
char str[num + 1]; scanf("%s", str);
for (int i = 0; i < num; i++)
{
// 读取到 '('
if (str[i] == '(')
{
// 若栈顶是 ')',即 将会形成 )(,出现一组不匹配的
if (stack[top-1] == ')')
{
// 交换两个,次数+2
ans += 2;
top--; // 把 ')' 从栈顶退出.
}
// 如果不是 ,就把他存入栈里
else stack[top++] = '(';
}
// 读取到 ')'
else
{
// 若栈顶是'(',能匹配,退栈.
if (stack[top-1] == '(') top--;
// 否则把')'入栈
else stack[top++] = ')';
}
}
// 如果还有括号没匹配在栈里,那么这个是不可能调整为合法的
if (top != 1) printf("-1");
else printf("%d", ans);
return 0;
}
总结:
这道题的合法非法说人话就是括号能不能匹配,那么又是一道栈的题目了.
那么怎么才算花费最少步数呢?如果想要重新调整成合法的话,那么至少每一个有问题的括号都得重新排序一次,因为每次重新排序都是针对两个字符,所以每排序一次都进行了两步.因此我们每遇到一组不匹配的我们便让答案+=2即可.
那么什么情况会无法转变为合法呢?显然当左右括号个数不相等时,绝对会出现无法匹配的括号.遇到此情况我们输出-1即可.反映到栈里,就是当结束循环后栈里仍有数据.
因此利用栈我们可以很快的解决问题.