LeetCode 301.删除无效的括号 DFS/BFS

本文探讨LeetCode上一道复杂题目:移除无效括号。通过深入解析,提出使用广度优先搜索(BFS)解决策略,确保找到最少删除次数下的所有解。同时,介绍如何判断括号字符串的有效性,以及实现代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述
题目链接:https://leetcode-cn.com/problems/remove-invalid-parentheses/

  • 首先,先说下这题很恶心,没给数据量
  • 这道题感觉类似于什么括号匹配的题目(用右括号去匹配左括号),而且是最小,可能是贪心这类的,但是这道题要求的是所有可能的结果,多出来的可能是左括号、也可能是右括号,且删掉一个可能使前面 k k k个字符满足了有效括号,后面的删除结果也要随之改变了。
  • 既然直接做会很麻烦,那么就暴力地去删除每一个字符,然后再对删除了一个的每一个串去删除第二个括号。每次删除都对已经删除括号个数相同的串进行,这很明显就是一层一层地去遍历解空间,没错就是bfs。
  • 因为是bfs,所以最先满足题意的串一定是删除个数最少的。这一层里其他满足题意的答案也一定是最少的。
  • 判断是否是有效的字符串:用一个变量 l l l去记录左括号的个数,出现右括号,说明可以匹配一个左括号: l l l- -,但是如果 l < 0 l<0 l<0,说明多出来了个右括号没有左括号与之匹配,直接返回 f a l s e false false。最后返回 l l l是否为0。
class Solution {
private:
    vector<string> ans;
    queue<string> Q;
    unordered_set<string> rec;
    bool isValid(const string & rhs){
        int l = 0;
        for (const char c: rhs){
            if (c == '(') l++;
            else if (c == ')') l--;
            if (l < 0) return false;
        }
        return l == 0;
    }
public:
    vector<string> removeInvalidParentheses(string s) {
        // bfs 暴力
        Q.push(s);
        int step = 0;
        bool flag = false;
        while (Q.size()){
            int s = Q.size();
            while (s-- > 0){
                string c = Q.front(); Q.pop();
                if (rec.count(c)) continue;
                rec.insert(c);

                if (isValid(c)) {
                    flag = true;
                    ans.push_back(c); continue;
                }

                string t;
                int n = c.length();
                for (int i = 0; i < n; i++){
                    t = c.substr(0, i) + c.substr(i + 1);
                    Q.push(t);
                }
            }
            if (flag) break;
        }
        return ans;
    }
};
  • 这题也可以选择用 d f s dfs dfs,我们可以选择像 b f s bfs bfs那样,每一次删除一个字符。也可以去构造字符,对每一个字符选或不选,构造。
class Solution {
private:
    vector<string> ans;
    queue<string> Q;
    unordered_set<string> rec;
    string s;
    int minDel = -1, n;

    void dfs(string cur, int idx, int del, int l){ // 最坏情况:O(2^n)
        if (minDel != -1 && del > minDel) return;
        if (l < 0) return;
        if (idx == n) {
            if (rec.count(cur)) return;
            rec.insert(cur);
            // cout << cur << "    ";

            if (l == 0){
                if (minDel == -1 || minDel > del) 
                    minDel = del, ans = {};

                if (minDel == del) ans.push_back(cur);
            }
            return;
        }

        if (s[idx] != '(' && s[idx] != ')') 
            dfs(cur + s[idx], idx + 1, del, l);
        else {
            dfs(cur, idx + 1, del + 1, l);

            if (s[idx] == ')') l--;
            else l++;
            dfs(cur + s[idx], idx + 1, del, l);
        }
    }

    bool isValid(const string & rhs){
        int l = 0;
        for (const char c: rhs){
            if (c == '(') l++;
            else if (c == ')') l--;
            if (l < 0) return false;
        }
        return l == 0;
    }

public:
    vector<string> removeInvalidParentheses(string s) {
        // 左括号用右括号去匹配
        this->s = s, this->n = s.length();
        rec.clear();
        dfs("", 0, 0, 0);
        cout << minDel;
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值