题目描述
给你一个由 '('、')' 和小写字母组成的字符串 s。
你需要从字符串中删除最少数目的 '(' 或者 ')' (可以删除任意位置的括号),使得剩下的「括号字符串」有效。
请返回任意一个合法字符串。
有效「括号字符串」应当符合以下 任意一条 要求:
空字符串或只包含小写字母的字符串 可以被写作 AB(A 连接 B)的字符串,其中 A 和 B 都是有效「括号字符串」 可以被写作 (A) 的字符串,其中 A 是一个有效的「括号字符串」
分析
输入: String, 让我们检查里面的括号可否全部闭合,如果不是那么去掉最少的括号
输出: String, 处理完成的字符串,里面没有括号或者括号均可闭合
解题思路
本题我们用一种不需要栈的方法,两次遍历这个字符串,首先去掉多余的右括号,再去掉多余的左括号,最后返回字符串。
第一轮:
声明一个计数器 cnt,表示左括号的个数,最后用来表示需要删多少个右括号,
声明一个空字符串 str,保存遍历到的所有合法的字符
然后遍历字符串,对当前字符分类讨论:
- (, 计数器加一,把左括号放入
str - ), 如果当前计数器是 0,说明这个右括号不合法,我们需要舍弃他,否则合法,放入
str - 其他,放入
str
这一轮,我们删除了没用的右括号。
第二轮与第一轮是一样的,只不过要删除的是没用的左括号~
最终,我们要返回的是第二轮的结果。
代码
/**
* @param {string} s
* @return {string}
*/
var minRemoveToMakeValid = function (s) {
let str = ""
let cnt = 0
for (let i = 0; i < s.length; i++) {
if (s[i] === "(") {
str += s[i]
cnt++
} else if (s[i] !== ")") {
str += s[i]
} else {
if (!cnt) continue
cnt--
str += s[i]
}
}
let ret = ""
let cnt2 = 0
for (let i = str.length - 1; i >= 0; i--) {
if (str[i] === ")") {
ret = ")" + ret
cnt2++
} else if (str[i] !== "(") {
ret = str[i] + ret
} else {
if (!cnt2) continue
cnt2--
ret = "(" + ret
}
}
return ret
}
复杂度
时间:O(N),字符串需要遍历两遍。
空间:O(N),存储的字符串最坏基本等于入参 s