Remove Invalid Parentheses 删除无效的括号

本文介绍了一种算法,用于删除字符串中最小数量的无效括号,使其成为有效的括号序列。通过回溯法找到所有可能的有效解,适用于包含除(和)外其他字符的输入。示例包括多种情况,如()())()、(a)())()和))(。文章详细解释了算法思路,包括找到多余的括号和限制有效括号数的方法。

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

删除最小数量的无效括号,使得输入的字符串有效,返回所有可能的结果。

说明: 输入可能包含了除 ( 和 ) 以外的字符。

示例 1:

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

示例 2:

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

示例 3:

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

这道题翻译了discuss的最高票解答(能看懂答案就不错了)

这道题的基本思想是找到多余的括号(注意是所有的),所以基本思路是采用回溯法找到所有有效解,然后加入答案中,先来看几点启发:

1:怎么找到多余的括号,在Valid Parentheses中,通过stack或者两个计数器left和right分别记录左括号和右括号的个数,可以验证一个左右括号是否符合要求。

2:如何限制在指定序列中的有效括号数,比如str=()()),采用计数方法(left和right计数器)来统计,发现left=2,right=3,由于left-right>=0,所以当前的子字符串多了一个右括号,需要删除一个),我们可以删除str[1],形成str=(()),也可以删除str[3],形成str=()(),为了避免重复出现答案,这里规定只删除第一个不符合要求的左括号,因为第二种情况会在后面的回溯中遍历到)。

我们规定几个变量的意思:start_to_count开始计数左右括号的位置,start_to_remove开始准备删除第一个不符合要求右括号的起始搜索点(start_to_remove<=start_to_count)

class Solution {
public:
    void Core(string s,vector<string> & res,int start_to_count,int start_to_remove,vector<char> &par){
        int count=0; //采用计数器来统计左右括号数
        for(int i=start_to_count;i<s.size();i++){
            if(s[i]==par[0]){
                count++; //遇到左括号就+1
            }
            if(s[i]==par[1]){
                count--; //遇到右括号就-1
            }
            if(count>=0) continue; 如果左括号个数>=右括号个数,继续寻找
            
            for(int j=start_to_remove;j<=i;j++){ //能进到for循环表示count小于0,表示一定要删除一个右括号,那么从start_to_remove开始寻找,找到第一个不满足要求的右括号的位置。
                if(s[j]==par[1] && (j==start_to_remove || s[j-1]!=par[1])){ //第一个多余的右括号的下标是s[j]==par[1],但是也要考虑边界条件:比如j是第一个元素这种情况
                    Core(s.substr(0,j)+s.substr(j+1),res,i,j,par); //那么删除第一个右括号后的有效字符串就是把第j个字符删掉的剩下的字符串,即new_str=s.substr(0,j)+s.substr(j+1),由于前面i个(下标)字符已经是有效的字符,且把第j个字符给删了,还要考虑新字符串new_str的长度少了1,那么新的开始搜索的字符下标new_start_to_count=i+1-1=i,同理new_start_to_remove=j+1-1,所以递归调用自身,对应参数设置如上所示。
                }
            }
            return;  //return这里已经处理了剩下子串的所有情况,直接返回,不然会有重复数据。
        }
        reverse(s.begin(),s.end()); //反转原字符,从右往左搜索删除多余的左字符
        if(par[0]=='('){
            vector<char> tmp={')','('};
            Core(s,res,0,0,tmp);
        }
        else res.push_back(s);
    }
    vector<string> removeInvalidParentheses(string s) {
        vector<char> par={'(',')'};
        vector<string> res;
        Core(s,res,0,0,par);
        return res;
    }
};

 

 

在C语言中,解决移除有效括号的问题通常涉及动态规划或栈的数据结构。题目通常是让你检查一个只包含左括号 `(`、右括号 `)` 的字符串,问能否通过删除某些括号得到一个有效的表达式,即左右括号的数量相等。这个问题可以转换为一种回溯算法,也可以使用深度优先搜索(DFS)结合栈来解决。 这里有一个基本的思路,使用栈来存储打开的括号,遇到关闭的括号时,如果栈不为空且顶部的括号是打开的,我们则弹出栈顶元素,表示可以合并这两个括号;否则,表示无法形成有效表达式,直接返回false。如果遍历完整个字符串后栈为空,说明可以完全配对,返回true。 以下是使用递归和栈的简单示例代码: ```c #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> bool isValid(char *s) { int openBrackets = 0; stack<char> brackets; for (int i = 0; s[i] != '\0'; ++i) { if (s[i] == '(') openBrackets++; else if (s[i] == ')') { if (openBrackets > 0) { openBrackets--; } else { return false; // Too many closing brackets } } } return openBrackets == 0; // Check if all opening brackets were closed } bool removeInvalidParentheses(char *s) { if (isValid(s)) return true; // No need to remove anything if already valid for (size_t i = 0; i < strlen(s); ++i) { if (s[i] != '(' && s[i] != ')') continue; // Recursive case: try removing this character char newS[strlen(s)]; memcpy(newS, s, i); memcpy(newS + i + 1, s + i + 1, strlen(s) - i - 1); bool isValidAfterRemoval = removeInvalidParentheses(newS); if (isValidAfterRemoval) { return true; } } return false; } int main() { char s[] = "()())"; if (removeInvalidParentheses(s)) { printf("Valid parentheses can be removed.\n"); } else { printf("Invalid parentheses cannot be removed.\n"); } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值