leetcode 301. 删除无效的括号 困难

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

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

示例 1:

复制代码
输入:s = "()())()"
输出:["(())()","()()()"]

示例 2:

复制代码
输入:s = "(a)())()"
输出:["(a())()","(a)()()"]

示例 3:

复制代码
输入:s = ")("
输出:[""]

提示:

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

分析:BFS 的核心是按"删除括号的数量"一层一层搜索。

把原字符串作为第 0 层。如果它不合法,就枚举删除其中一个括号,得到第 1 层的所有字符串;如果第 1 层仍然没有合法结果,就继续删除一个括号,得到第 2 层。

由于 BFS 是按删除次数递增搜索的,所以第一次出现合法字符串时,这一层对应的删除次数一定是最少的。此时收集这一层所有合法字符串,直接结束搜索,不需要继续往下一层。

搜索过程中要使用集合进行去重,避免同一个字符串被重复加入队列。连续相同的括号也可以跳过重复删除的位置,进一步减少搜索量。

判断字符串是否合法时,从左到右扫描:遇到 ( 计数加一,遇到 ) 计数减一。如果中途计数小于 0,说明出现了无法匹配的右括号;最后计数为 0,则说明括号完全匹配。

因此整体思路就是:

原字符串 → 删除 1 个括号的所有情况 → 删除 2 个括号的所有情况 → ......

第一次找到合法字符串的那一层,就是最终答案。

cpp 复制代码
class Solution {
public:
    vector<string> removeInvalidParentheses(string s) {
        vector<string>ans;
        queue<string>q;q.push(s);
        unordered_set<string>visited;visited.insert(s);

        bool found=false;
        while(!q.empty())
        {
            int size=q.size();
            for(int k=0;k<size;k++)
            {
                string cur=q.front();q.pop();
                if(isValid(cur))
                    ans.push_back(cur),found=true;

                if(found)continue;

                for(int i=0;i<cur.size();i++)
                {
                    if(cur[i]!='('&&cur[i]!=')')continue;
                    
                    if(i>0&&cur[i]==cur[i-1])continue;

                    string next=cur.substr(0,i)+cur.substr(i+1);

                    if(!visited.count(next))
                        visited.insert(next),q.push(next);
                }
            }
            if(found)break;
        }

        return ans;
    }

    bool isValid(const string &s)
    {
        int cnt=0;
        for (int i=0;s[i];++i)
        {
            char c=s[i];
            if(c=='(')cnt++;
            else if (c == ')')
            {
                cnt--;
                if(cnt<0)return false;
            }
        }
        return cnt==0;
    }
};
相关推荐
夏幻灵3 小时前
每日一题:LeetCode 206:反转链表——三指针与原地反转详解
算法·leetcode·链表
Tisfy7 小时前
LeetCode 0301.删除无效的括号:二进制枚举 / 回溯
算法·leetcode·字符串·题解·回溯·括号匹配·二进制枚举
Nil2087 小时前
leetcode 322零钱兑换
算法·leetcode·职场和发展
yi0117 小时前
DAY24: LeetCode 167:两数之和 II|从暴力枚举到左右双指针
笔记·python·算法·leetcode·二分查找·双指针
木井巳7 小时前
【BFS 解决拓扑排序】课程表
java·算法·leetcode·广度优先·宽度优先·推荐算法·图搜索算法
yi0118 小时前
LeetCode 15:三数之和|排序 + 双指针,如何避免重复答案?
笔记·python·算法·leetcode·双指针
alphaTao8 小时前
LeetCode 每日一题 2026/10/5-2026/10/11
算法·leetcode
longlongzihan11 小时前
LeetCode 41. 缺失的第一个正数:从基础解法到原地哈希
c++·算法·leetcode
java_nnnn12 小时前
LeetCode刷题双指针(快乐数+盛最多水的容器)Java
算法·leetcode·职场和发展