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;
    }
};
相关推荐
j7~16 小时前
【穷举、深搜与回溯算法】一棵决策树讲透全排列与子集
数据结构·c++·算法·leetcode·回溯·递归
Shaoshing18 小时前
LeetCode100 42.接雨水
java·算法·leetcode
文丑颜不良啊19 小时前
LeetCode1261~1280题目解析
java·leetcode
Shaoshing20 小时前
LeetCode100 11. 盛最多水的容器
算法·leetcode
海绵宝宝转agent20 小时前
Leetcode二叉树算法个人理解
笔记·学习·算法·leetcode·深度优先
Rain的Java大神之路21 小时前
面试被LeetCode 27(移除元素)问懵?别再用两层 for 循环了:一道“简单题”吃透双指针原地删除,附面试加分话术 + 11 个避坑清单
后端·leetcode·面试
重生之小比特1 天前
【算法拾光】前缀和|连续的子数组和 + 和相同的二元子数组
算法·leetcode·哈希算法
Pniubi1 天前
力扣 102二叉树的层序遍历(广度优先搜索)
leetcode·宽度优先
一去不复返的通信er1 天前
力扣15:盛最多水的容器
算法·leetcode
Navigator_Z1 天前
LeetCode //C - 1309. Decrypt String from Alphabet to Integer Mapping
c语言·算法·leetcode