301. 删除无效的括号

297 阅读1分钟

这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战

301. 删除无效的括号

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

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

  • 示例 1:

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

  • 示例 2:

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

  • 示例 3:

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

提示:

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

解题思路

使用广度优先搜索,对上一次产生的字符串的每个括号,逐个尝试删除,每次bfs等于删除一个括号,当出现合法的字符串时,就将其加入结果数组.

在进行广度优先搜索时,每次保存上一轮BFS的结果,然后对上一轮已经保存的结果中的每一个字符串尝试所有可能的删除一个括号的方法,然后利用保存的结果进行下一轮搜索。在保存结果时,我们可以利用SET对上一轮生成的结果去重,从而提高效率。

代码

class Solution {
public:
    vector<string> removeInvalidParentheses(string s) {

        vector<string> res;
        unordered_set<string> set;
        set.insert(s);
        while (true) {
            for (string t:set) {
                if (is_valid(t))
                    res.push_back(t);
            }
            if (res.size() > 0)
                return res;
            unordered_set<string> new_set;
            for (string t:set) {
                for (int i = 0; i < t.length(); ++i) {
                    if (t[i]=='('||t[i]==')')
                        new_set.insert(t.substr(0,i)+t.substr(i+1));
                }
            }
            set=new_set;
        }
        return res;


    }

    bool is_valid(string s) {
        int l = 0;
        for (char c:s) {
            if (c == '(')
                l++;
            else if (c == ')')
                l--;
            if (l < 0)
                return false;
        }
        return l==0;
    }
};

时间复杂度:O(n * 2^n),其中 n 为字符串的长度。考虑到一个字符串最多可能有 2^n个子序列,因此时间复杂度为 O(n * 2^n)。

空间复杂度: O(n×Cnn2)O(n \times C_n^\frac{n}{2}),其中 n 为字符串的长度。我们在进行第 i 轮迭代时,会从原始字符串中删除 i个括号,因此第 i 轮迭代产生的字符串最多有 CniC_n^i 个,当 i=n2i = \frac{n}{2} 时组合数最大,此时迭代生成的字符串个数最多,因此空间复杂度为 O(n×Cnn2)O(n \times C_n^\frac{n}{2})