题目
一个完整的括号字符串定义规则如下:
①空字符串是完整的。
②如果s是完整的字符串,那么(s)也是完整的。
③如果s和t是完整的宇符串,将它们连接起来形成的st也是完整的。
例如,"(()())",和"(())()"是完整的括号字符串,"())(","()(",")"是不完整的括号字符串。
牛牛有一个括号字符串s,现在需要在其中任意位置尽量少地添加括号,将其转化为一个完整的括号字符串。请问牛牛至少需要添加多少个括号。
- 判断是否是完整字符串:通过一个变量count来记录从左往右遇到的"("数量,如果遇到")"则数量减1,如果count<0说明需要添加"(",>0需要添加")",=0时为完整的字符串
- 如果不是完整字符串:在遍历过程中,如果<0了,则说明要添加1个左括号,此时补齐了成了完整字符串,然后恢复count为0,如果整体遍历结束了count>0了,说明需要添加count数量个右括号,最后答案count+之前过程中补齐的左括号
- 为什么不能根据遍历完成后count的值来直接添加左括号或右括号,是因为'))((' 最后count为0,但实际上要添加4个括号
function process(str) {
let count = 0;
let addLeft = 0;
for (let i = 0; i < str.length; i++) {
if (str[i] === "(") {
count++;
} else {
//等价于 count为-1时,添加一个左括号然后将count恢复为0
if (count === 0) {
addLeft++;
} else {
count--;
}
}
}
return count + addLeft;
}
题目
在完整字符串的基础上如果给定的字符串都是完整字符串,如果x串深度为x,y串深度为y,则xy串深度为max(x,y),比如:""深度为0,"(())"深度为2,"(())()"深度为max(2,1)为2,计算给定完整字符串的深度
- 在上一题的基础上,count的最大值就是最大深度,因为每当count为0时,说明一个完整字符串匹配结束
题目
求给字符串中最长完整字符串的长度
- 首先以"("结尾不可能构成完整字符串所以长度为0,以")"结尾的最长子串等于起-1位置的最长完整子串+2,2为左右边界括号的数量,然后还要加上当前最长子串前面是否还有最长完整子串,不用考虑前面的前面是否还有最长子串,因为是从子问题开始累加,前面的答案已经包含了所有子问题的答案
function process(str) {
let max = 0;
const dp = []; // 记录每一个以当前符号结尾的最长完整子串长度
for (let i = 0; i < str.length; i++) {
if (str[i] === "(") {
dp[i] = 0;
}
}
dp[0] = 0;
for (let i = 1; i < str.length; i++) {
if (str[i] === ")") {
const preIndex = i - dp[i - 1] - 1; // 与str[i]配对的'('位置index,中间位置长度为dp[i-1]即")"左边一位的最长完整子串长度
if (preIndex >= 0 && str[preIndex] === "(") {
// 当前位置前一位的最长子串+2表示当前位置最长完整子串(x)+ 如果前面还有完整子串(y)
// 不用担心前面的前面还是完整子串,因为是从子问题开始,每一个最长完整子串的结果都包含了上一次的结果,比如 c 包含了 b, b 包含了 a,d 包含了 c 也就包含了 ba
dp[i] = dp[i - 1] + 2 + dp[preIndex - 1];
}
}
max = Math.max(max, dp[i]);
}
return res;
}