一、题目描述
给你一个由 '('、')' 和小写字母组成的字符串 s。
你需要从字符串中删除最少数目的 '(' 或者 ')' (可以删除任意位置的括号),使得剩下的「括号字符串」有效。
请返回任意一个合法字符串。
有效「括号字符串」应当符合以下 任意一条 要求:
- 空字符串或只包含小写字母的字符串
- 可以被写作
AB(A连接B)的字符串,其中A和B都是有效「括号字符串」 - 可以被写作
(A)的字符串,其中A是一个有效的「括号字符串」
示例 1:
输入: s = "lee(t(c)o)de)"
输出: "lee(t(c)o)de"
解释: "lee(t(co)de)" , "lee(t(c)ode)" 也是一个可行答案。
复制代码
示例 2:
输入: s = "a)b(c)d"
输出: "ab(c)d"
复制代码
示例 3:
输入: s = "))(("
输出: ""
解释: 空字符串也是有效的
复制代码
示例 4:
输入: s = "(a(b(c)d)"
输出: "a(b(c)d)"
复制代码
提示:
1 <= s.length <= 10^5s[i]可能是'('、')'或英文小写字母
分析
- 计算最少删除的数量,看到我就想着贪心,能留则留,加个结果
result,每一轮如果符合条件就加进来; - 从左往右遍历,用变量
count记录左括号出现的次数,如果遇到"("就加一, 遇到")"就减一; - 当
count为0时,遇到")"直接删除,因为前面没有可以匹配的"("; - 遍历结束后,如果
count有剩余,那么我们需要删除多余的"("; - 这时候我们发现我们不知道哪里有"(",所以我们可以回到第二步,把
count换成stack数组; - 从左往右遍历,如果遇到"("就
push当前元素在result的索引, 遇到")"就pop取出最后一个对应"("; - 当
stack.length为0时,遇到")"直接删除,因为前面没有可以匹配的"("; - 遍历结束后,删除
stack中残留的索引。
代码实现
/**
* @param {string} s
* @return {string}
*/
var minRemoveToMakeValid = function(s) {
const n = s.length;
let result = "";
let stack = [];
for (let i = 0; i < n; i++) {
if (s[i] === "(") {
// 上一轮末尾元素的索引等于长度减1,当前索引又得加1,相互抵消
stack.push(result.length);
result += s[i];
} else if (s[i] === ")") {
if (stack.length) {
stack.pop();
result += s[i];
}
} else {
result += s[i];
}
}
// 删除多余的左括号
while (stack.length) {
let cur = stack.pop();
// 删除第i个位置的字符串
result = result.slice(0, cur) + result.slice(cur + 1);
}
return result;
};
欢迎留言讨论哦