移除无效的括号

486 阅读2分钟

正题

移除无效的括号

给你一个由 '('、')' 和小写字母组成的字符串 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. 遍历字符串,仅仅针对 ( )两个括号进行逻辑判断,其余字符忽略。

  2. 建立栈空间,对遍历的 ( ) 进行 push , pop 操作。

  3. 当出现 ( 时,直接 push 进栈

  4. 当出现 )时,有两种情况

    4.1. 前一个是 ( 说明该有括号和左括号可以组成闭合,都是有效括号,那么 该)不必压入栈中,并且将 ( 弹出

    4.2. 前一个也是 ) 说明该括号必然无效,因为前一个 )都没有匹配了,当前这个更匹配不到。则将该字符压入栈中。

  5. 将栈中的元素下标遍历,从数组中删除对应下标。

主要代码:

/**
 * @param {string} s
 * @return {string}
 */
var minRemoveToMakeValid = function(s) {
    let stack = []
    for(let index = 0 ; index < s.length ; index++) {
        const char = s[index]
        // 第一个出现的必然进栈
        if (stack.length === 0 && (char === '(' || char === ')')) {
            stack.push({char, index})
            continue
        }
        if (char === ')') {
            if (stack[stack.length - 1].char === '(') {
                stack.pop()
            } else {
                stack.push({char, index})
            }
        } else if (char === '(') {
            stack.push({char, index})
        }
    }
    stack = stack.map(i => {return i.index})
    let count = 0
    s = s.split('')
    while(count < stack.length) {
        s.splice(stack[count] - count, 1)
        count++
    }
    return s.join('')
};