leetcode hot100之删除无效的括号(301)解析

143 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第30天,点击查看活动详情


前言

  • leetcode hot100,是大厂面试高频题,也是必刷算法题。精选了100道LeetCode上最热门的题目,适合初识算法与数据结构的新手和想要在短时间内高效提升的人,按照官方说的,熟练掌握这 100 道题,就具备了代码世界通行的基本能力。

leetcode301题(删除无效的括号)

本文来讲hot100第301题(删除无效的括号),本题是括号类型的题目,本题解主要是用到和回溯+减枝,此题如果不理解括号匹配规则,建议先把20题“有效的括号”先做一下。

给你一个由若干括号和字母组成的字符串 s ,删除最小数量的无效括号,使得输入的字符串有效。

返回所有可能的结果。答案可以按 任意顺序 返回。

示例:

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

提示:

  • 1 <= s.length <= 25
  • s 由小写英文字母以及括号 '(' 和 ')' 组成
  • s 中至多含 20 个括号

分析

  • 字符串由“字母”与“数字”构成
  • 括号是成对存在的,所以删除n个括号后,最终的括号量一定是个偶数
  • 删除最小数量的括号,可能这个最小数量会有多种结果,所以是返回数组
  • 字符串是否合理与字母无关

思路

  1. 先一次遍历计算出多余的左括号和右括号
    • 如果是左括号,则left ++
    • 如果是右括号,判断left是不是为0,不为0则left--,为0则right++
    • 通过这样的计数规则,可以算出左括号和右括号需要删除的最小数量
  2. 使用回溯算法遍历,去掉不合法的括号(需要减枝)
  3. 针对2,我们需要使用个方法判断是否合法

代码

var removeInvalidParentheses = function (s) {
  let l = 0,
    r = 0;
  const ans = [];
  for (const char of s) {
    if (char === "(") {
      l++;
    }
    if (char === ")") {
      if (l === 0) {
        r++;
      } else {
        l--;
      }
    }
  }

  // 回溯算法 + 减枝
  function helper(str, start, l, r) {
    if (l === 0 && r === 0) {
      if (isValid(str)) {
        ans.push(str);
      }
      return;
    }

    for (let i = start; i < str.length; i++) {
      if (i !== start && str[i] === str[i - 1]) {
        continue;
      }
      // 如果剩余的字符无法满足去掉的数量要求,直接返回
      if (l + r > str.length - i) {
        return;
      }
      // 尝试去掉一个左括号
      if (l > 0 && str[i] === "(") {
        helper(str.substr(0, i) + str.substr(i + 1), i, l - 1, r);
      }
      // 尝试去掉一个右括号
      if (r > 0 && str[i] === ")") {
        helper(str.substr(0, i) + str.substr(i + 1), i, l, r - 1);
      }
    }
  }

  helper(s, 0, l, r);
  return ans;
};

function isValid(str) {
  let cnt = 0;
  for (const char of str) {
    if (char === "(") {
      cnt++;
    } else if (char === ")") {
      cnt--;
      if (cnt < 0) {
        return false;
      }
    }
  }
  return cnt === 0;
}

结语

本题解复杂点主要在于helper方法,不仅仅需要理解括号匹配规则,还需要知道回溯+减枝的方法,时间复杂度O(n * 2^n),空间复杂度O(n^2)