[路飞]_移除无效的括号

144 阅读1分钟

题目介绍

给你一个由 '('')' 和小写字母组成的字符串 s

你需要从字符串中删除最少数目的 '(' 或者 ')' (可以删除任意位置的括号),使得剩下的「括号字符串」有效。

请返回任意一个合法字符串。

有效「括号字符串」应当符合以下 任意一条 要求:

  • 空字符串或只包含小写字母的字符串
  • 可以被写作 ABA 连接 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,当遇到 ')' 且标志位大于 0 时,将标志位 -1,如果标志位为 0,说明该位置的 ')' 非法,需要将该 ')' 移除

执行完上述过程之后,我们已经将多余的 ')' 全部移除了,这时候还可能存在多余的 '(',有两种方法可以移除非法的 '(':

  1. 反向执行上述步骤,将多余的 '(' 移除
  2. 从右往左,'(' 比 ')' 多了几个,我们就删除几个 '('

步骤:

  1. 定义一个空数组 arr 和标记位 sign, 遍历 s 字符串
  2. 遇到 '(' 或者 小写字母时,将其放到数组中,如果是 '(',将 sign+1
  3. 如果遇到 ')'sign > 0,说明 ')' 合法,将其放到数组中,同时 sign-1;如果 sign <= 0,说明该位置不合法,直接跳过
  4. 执行完以上步骤,如果 sign0,表示 '('')' 一样多,直接返回 arr 拼接成字符串即可;如果 sign 不为 0sign 为多少则表示 '('')' 多了几个,直接从右往左删除 sign'(' 即可,再返回 arr 拼接成字符串

1.gif

解题代码

var minRemoveToMakeValid = function(s) {
    const arr = []
    let sign = 0
    for (let i = 0; i < s.length; i++) {
        if (s[i] !== ')') {
            if (s[i] === '(') sign++
            arr.push(s[i])
        } else if (sign > 0) {
            sign--
            arr.push(s[i])
        }
    }
    if (!sign) return arr.join('')
    for (let i = 0; i < sign; i++) {
        arr.splice(arr.lastIndexOf('('), 1)
    }
    return arr.join('')
};