题目

题目大题就是给定一个括号序列,其中仅包含()*,任务就是替换其中的*为()或者空字符串,是的原字符串平衡且字典序最小。
一个不难想象到的是,最终的解法应该是在字符串的两侧不断替换括号,且两种括号的添加不能发生交叉。试想,如果替换出现了这种情况...)...(...。那么直接去掉这两个将会是长度更小的答案,所以这种情况是不会出现的。
为了解决问题,不妨将需要解决的问题分成两个步骤
- 使括号数量平衡
- 使括号配对平衡
首先拿到序列先在一侧添加括号,使得左右括号一样多。达成这一点很简单,扫描一遍整个数组即可。
在扫描的过程中,还能完成另一项任务:判定是否有解!!准确些说,就是对于一个位置前面的)多于(和*的总和,或者一个位置后面的(多于)和*的总和。这个在一次正向遍历中就能解决。
判断完结果后,把缺少的括号补充在一侧即可
scanf("%s",str);
n = strlen(str);
cntL = cntR = 0;
L = R = 0;
for(int i = 0;i < n && R >= 0;i++){
if(str[i] == '('){
L++;
cntL++;
}else{
(--L) < 0 && (L = 0);
}
if(str[i] == ')'){
R--;
cntR++;
}else{
R++;
}
}
if(L > 0 || R < 0){
printf("No solution!\n");
continue;
}
for(int i = 0;i < n && cntR - cntL > 0;i++){
if(str[i] == '*'){
str[i] = '(';
cntL++;
}
}
for(int i = n - 1;i >= 0 && cntL - cntR > 0;i--){
if(str[i] == '*'){
str[i] = ')';
cntR++;
}
}
经过上面的操作,两种括号的数量平衡了,可以说明的是现在待处理的问题串变成了这个亚子:....).)).))...(((.((....
省略掉的是*和已经配好对的括号。且这里不难看出,两种未配对的括号各处一边,数量相等。 且经过上面的筛选,解是一定存在的。
下面的任务就是找到这些括号的数量了,有两种思路,一种是二分试出来,另一种是贪心的思想遍历一下找出来。
二分
对填充一种括号的数量进行二分,下限是0,上限是剩余*数量的一半(因为括号要成对添加)。
每次枚举出数量放进去试一试,不合法就是少了,合法就是正好或者多了。
二分代码:
L = 0;
R = (n - cntL - cntR) >> 1;
int M,cnt;
while(L < R){
M = (L + R) >> 1;
strcpy(temp,str);
for(int i = n - 1,suf = M;i >= 0,suf > 0;i--){
if(temp[i] == '*'){
temp[i]

最低0.47元/天 解锁文章
962

被折叠的 条评论
为什么被折叠?



