301 删除无效的括号

题目描述:
删除最小数量的无效括号,使得输入的字符串有效,返回所有可能的结果。
说明: 输入可能包含了除 ( 和 ) 以外的字符。

示例 1:
输入: “()())()”
输出: ["()()()", “(())()”]

示例 2:
输入: “(a)())()”
输出: ["(a)()()", “(a())()”]

示例 3:
输入: “)(”
输出: [""]

方法1:
参考代码
主要思路:
(1)先统计出要删除的左括号和右括号的数量;
(2)使用递归生成需要的字符串,具体看代码;
(3)为了去除重复的元素,使用unordered_set进行去重,最后将unordered_set转成vector返回;

class Solution {
public:
	//递归
    void dfs(string& s,unordered_set<string>& st,string path,int erase_l,int erase_r,int index,int diff){
        if(index==s.size()){//在索引满足要求时
            if(diff==0){//若已经加入到当前字符串的左右括号的数量满足要求,则是符合要求的字符串
                st.insert(path);
            }
            return;
        }
        //若当前字符是左括号
        if(s[index]=='('){
        	//将当前左括号加入到当前字符串中
            dfs(s,st,path+s[index],erase_l,erase_r,index+1,diff+1);
            if(erase_l>0){//若还能够删除左括号,则尝试跳过当前括号,既相当于删除当前左括号,继续递归
                dfs(s,st,path,erase_l-1,erase_r,index+1,diff);
            }
        }
        else if(s[index]==')'){//若当前字符是右括号
            if(diff>0){//若当前字符串中左括号更多,说明可以将当前的右括号加入到当前字符串中
                dfs(s,st,path+s[index],erase_l,erase_r,index+1,diff-1);
            }
            if(erase_r>0){//若还能够删除右括号,则尝试跳过右括号,既相当于删除右括号,继续递归
                dfs(s,st,path,erase_l,erase_r-1,index+1,diff);
            }
        }
        else{//若当期字符不是括号,则直接添加到当前字符串中
            dfs(s,st,path+s[index],erase_l,erase_r,index+1,diff);
        }
    }
    vector<string> removeInvalidParentheses(string s) {
    	//分别统计左右括号需要删除的数量
        int erase_l=0;
        int erase_r=0;
        for(char&ch:s){
            if(ch=='('){
                ++erase_l;//统计右括号的数量
            }
            else if(ch==')'){
                if(erase_l==0){
                    ++erase_r;//没有可匹配的左括号时,统计右括号的数量
                }
                else{
                    --erase_l;//在可以和右括号匹配时,减少左括号的数量
                }
            }
        }
        unordered_set<string> st;//用于去重字符串,并存储字符串
        dfs(s,st,"",erase_l,erase_r,0,0);
        return vector<string> (st.begin(),st.end());//返回vector
    }
};

方法2:
主要思路:
(1)该方法是对方法1的优化,既直接在生成当前字符串时避免生成重复的字符串,不再使用unordered_set进行去重;
(2)主要是通过一次找出所有的连续的重复的括号的个数,进行递归;

class Solution {
public:
    void dfs(string& s,vector<string>& res,string path,int erase_l,int erase_r,int index,int diff){
    	//终止条件,既遍历到了字符串的末尾
        if(index==s.size()){
            if(diff==0){//若条件满足,则将当前字符串压入到结果中
                res.push_back(path);
            }
            return;
        }
        if(s[index]=='('){//若当前字符是左括号
        	//找出连续的左括号的范围的右边的索引
            int k=index;
            while(k<s.size()&&s[k]=='('){
                ++k;
            }
            //先假设删除该段的所有的左括号
            erase_l-=k-index;
            //该循环中,逐渐添加左括号,直到不需要删除左括号的情形
            for(int i=k-index;i>=0;--i){
                if(erase_l>=0){//说明此时是合理的删除范围,可以递归进行判断,注意索引的起始点一直是 k
                    dfs(s,res,path,erase_l,erase_r,k,diff);
                }
                //逐渐的添加左括号
                path+='(';
                ++diff;
                ++erase_l;
            }
        }
        else if(s[index]==')'){//当前的字符是右括号
        	//找出连续的右括号范围的右边的索引
            int k=index;
            while(k<s.size()&&s[k]==')'){
                ++k;
            }
            //先假设删除该段的所有的右括号
            erase_r-=k-index;
            //该循环中,逐渐的添加右括号,直到不需要删除右括号的情形
            for(int i=k-index;i>=0;--i){
            	//若当前字符可删除,且是合理的字符串(合理是指当前字符串中左括号的数量是大于右括号的数量的),则进行递归调用
                if(diff>=0&&erase_r>=0){
                    dfs(s,res,path,erase_l,erase_r,k,diff);
                }
                //添加右括号
                path+=')';
                --diff;
                ++erase_r;
            }
        }
        else{//正常的将非括号的字符添加到字符串中
            dfs(s,res,path+s[index],erase_l,erase_r,index+1,diff);
        }
    }
    vector<string> removeInvalidParentheses(string s) {
    	//统计需要删除的左右括号的数量
        int erase_l=0;
        int erase_r=0;
        for(char&ch:s){
            if(ch=='('){
                ++erase_l;
            }
            else if(ch==')'){
                if(erase_l==0){
                    ++erase_r;
                }
                else{
                    --erase_l;
                }
            }
        }
        //直接存储字符串
        vector<string> res;
        dfs(s,res,"",erase_l,erase_r,0,0);
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本系统的研发具有重大的意义,在安全性方面,用户使用浏览器访问网站时,采用注册和密码等相关的保护措施,提高系统的可靠性,维护用户的个人信息和财产的安全。在方便性方面,促进了校园失物招领网站的信息化建设,极大的方便了相关的工作人员对校园失物招领网站信息进行管理。 本系统主要通过使用Java语言编码设计系统功能,MySQL数据库管理数据,AJAX技术设计简洁的、友好的网址页面,然后在IDEA开发平台中,编写相关的Java代码文件,接着通过连接语言完成与数据库的搭建工作,再通过平台提供的Tomcat插件完成信息的交互,最后在浏览器中打开系统网址便可使用本系统。本系统的使用角色可以被分为用户和管理员,用户具有注册、查看信息、留言信息等功能,管理员具有修改用户信息,发布寻物启事等功能。 管理员可以选择任一浏览器打开网址,输入信息无误后,以管理员的身份行使相关的管理权限。管理员可以通过选择失物招领管理,管理相关的失物招领信息记录,比如进行查看失物招领信息标题,修改失物招领信息来源等操作。管理员可以通过选择公告管理,管理相关的公告信息记录,比如进行查看公告详情,删除错误的公告信息,发布公告等操作。管理员可以通过选择公告类型管理,管理相关的公告类型信息,比如查看所有公告类型,删除无用公告类型,修改公告类型,添加公告类型等操作。寻物启事管理页面,此页面提供给管理员的功能有:新增寻物启事,修改寻物启事,删除寻物启事。物品类型管理页面,此页面提供给管理员的功能有:新增物品类型,修改物品类型,删除物品类型。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值