题目:点击打开链接
题解:
不能用栈,会爆栈
全部转化成不匹配,要不就是全化为((((或))))或))))((((这三种情况必居其一
思路是从左到右和从右到左各扫描一次记录 ( 和 ) 的到每个位置的数量,
遍历一下将每个位置的左方全转置成 ) 和右方全转置成 ( 需要的次数和,凑成))))((((的情况,求最小的那个,这么算发现有一个转置是不必要的,注意减一
根据下面这个样例会比较容易理解
下面这个是的i和l[i]和r[i]
i 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
l[i] 0 0 0 1 1 2 3 3 3 3 4 5 6 6 7 8 9
r[i] 8 7 6 5 5 4 4 4 3 2 1 1 1 1 0 0 0
结果是当i=11时最小,为4
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
#define INF 0x3f3f3f3f
char s[1010];
int l[1010],r[1010];
int main()
{
int t;
cin>>t;
while(t--)
{
scanf("%s",s);
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
int len=strlen(s);
for(int i=len-1;i>=0;i--)
{
if(i==len-1)
r[i]=(s[i]==')');//统计)的个数
else
r[i]=r[i+1]+(s[i]==')');
}
for(int i=0;i<len;i++)
{
if(i==0)
l[i]=(s[i]=='(');//统计(的个数
else
l[i]=l[i-1]+(s[i]=='(');
}
int ans=INF;//很大
for(int i=0;i<len;i++)
ans=min(ans,l[i]+r[i]-1);
printf("%d\n",ans);
}
return 0;
}