删除无效的括号

299 阅读2分钟

题目:

给你一个由若干括号和字母组成的字符串 s ,删除最小数量的无效括号,使得输入的字符串有效。 返回所有可能的结果。答案可以按 任意顺序 返回。   示例 1: 输入:s = "()())()" 输出:["(())()","()()()"]

示例 2: 输入:s = "(a)())()" 输出:["(a())()","(a)()()"]

示例 3: 输入:s = ")(" 输出:[""]

解题思路:

首先需要判断字符串是否有效:
  • 就是遇到左括号,计数 +1
  • 遇到字母不算,遇到右括号,计数 -1
  • 计数为负,说明右括号在前了,直接返回无效
  • 否则循环完整个字符串,计数为 0 则有效
const valid = function (str) {
  let count = 0;
  for (let c of str) {
    if (c === '(') {
      count++;
    } else if (c === ')') {
      count--;
    }

    if (count < 0) {
      return false;
    }
  }
  return count === 0;
}

然后尝试删除字符串中每一个括号字符,并检查是否有效:
  • 如果当前字符和前一位字符相同,则不必尝试,因为效果是一样的
  • 只删除当前字符,并重新组合成新的字符串
  • 因为有字母,字母不用删,只删除左右括号,将所有的可能都放入一个 Set 里,因为 Set 自动去重。
let str = s;
let set = new Set();
for (let i = 0; i < str.length; i++) {
  if (i > 0 && str[i] == str[i - 1]) {
    continue;
  }
  if (str[i] === '(' || str[i] === ')') {
    let temp = str.substring(0, i) + str.substring(i + 1);
    set.add(temp);
  }
}
  • 有可能需要删除多个字符才能合理,所以上一次循环的字符串作为下一次删除字符的模版
let curSet = new Set();
curSet.add(s);
for (let str of curSet) {
  let nextSet = new Set();
  for (let i = 0; i < str.length; i++) {
    if (i > 0 && str[i] == str[i - 1]) { continue; }
    if (str[i] === '(' || str[i] === ')') {
      let temp = str.substring(0, i) + str.substring(i + 1);
      nextSet.add(temp);
    }
  }
  curSet = nextSet;
}
  • 最后,要求返回的是删除最小数量字符,所以一旦有合理的字符串产生,就可以结束了
let curSet = new Set();
curSet.add(s);
let ans = [];
while (true) {
  for (let t of curSet) {
    if (valid(t)) {
      ans.push(t);
    }
  }

  if (ans.length > 0) { return ans; }

  let nextSet = new Set();
  for (let str of curSet) {
    for (let i = 0; i < str.length; i++) {
      if (i > 0 && str[i] == str[i - 1]) {
        continue;
      }
      if (str[i] === '(' || str[i] === ')') {
        let temp = str.substring(0, i) + str.substring(i + 1);
        nextSet.add(temp);
      }
    }
  }
  curSet = nextSet;
}

完整代码:

/**
 * @param {string} s
 * @return {string[]}
 */
var removeInvalidParentheses = function(s) {
  const valid = function (str) {
    let count = 0;
    for (let c of str) {
      if (c === '(') {
        count++;
      } else if (c === ')') {
        count--;
      }

      if (count < 0) {
        return false;
      }
    }
    return count === 0;
  }
  
  let curSet = new Set();
  curSet.add(s);
  let ans = [];

  while (true) {
    for (let t of curSet) {
      if (valid(t)) {
        ans.push(t);
      }
    }

    if (ans.length > 0) { return ans; }

    let nextSet = new Set();
    for (let str of curSet) {
      for (let i = 0; i < str.length; i++) {
        if (i > 0 && str[i] == str[i - 1]) {
          continue;
        }
        if (str[i] === '(' || str[i] === ')') {
          let temp = str.substring(0, i) + str.substring(i + 1);
          nextSet.add(temp);
        }
      }
    }
    curSet = nextSet;
  }
};

整理不易,都看到这里了,就点个赞吧