ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

力扣题301删除无效的括号

2021-12-17 18:58:57  阅读:162  来源: 互联网

标签:charAt 括号 int 301 力扣题 leftRemove ++ str


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

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

示例 1:

输入:s = "()())()"
输出:["(())()","()()()"]
示例 2:

输入:s = "(a)())()"
输出:["(a())()","(a)()()"]
示例 3:

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

题解:力扣

1.回溯加剪枝。

class Solution {
    List<String> list = new ArrayList<>();

    public List<String> removeInvalidParentheses(String s) {
        // 统计需要移除的左括号数或右括号数
        int leftRemove = 0;
        int rightRemove = 0;
        for (int i = 0;i < s.length();i++) {
            char cur = s.charAt(i);
            if (cur == '(') { // 遇到左括号,就给左括号需要移除的数量加1
                leftRemove++;
            } else if (cur == ')') { // 遇到右括号
                if (leftRemove > 0) { // 如果此时左括号需要移除的数量大于0,就用现在遍历到的右括号抵消左括号
                    leftRemove--;
                } else { // 如果此时左括号需要移除的数量等于0,就说明现在遍历到的右括号是需要移除的
                    rightRemove++;
                }
            }
        }

        helper(s,0,0,0,leftRemove,rightRemove);
        
        return list;
    }

    public void helper(String s,int index,int leftCount,int rightCount,int leftRemove,int rightRemove) {
        if (leftRemove == 0 && rightRemove == 0) { //此时需要移除的数量都移除完了
            if (isValid(s)) { //如果移除后的字符串是有效的,就加入list中
               list.add(s); 
            }
            return;
        }

        for (int i = index;i < s.length();i++) {
            char cur = s.charAt(i);
            if (i == index || cur != s.charAt(i-1)) { // 这里如果相邻的相等那么删除哪个都是一样的,避免重复
                if (leftRemove + rightRemove > s.length() - i) { // 剩余的括号数已经不够减了,直接返回
                    return;
                }

                if (leftRemove > 0 && cur == '(') { // 如果当前值是左括号,并且左括号有需要删除的数量,就把当前遍历到的左括号删除
                    // 在删除当前左括号后的子串上继续向后删除
                    helper(s.substring(0,i) + s.substring(i + 1),i,leftCount,rightCount,leftRemove - 1,rightRemove);
                }

                if (rightRemove > 0 && cur == ')') {
                    helper(s.substring(0,i) + s.substring(i + 1),i,leftCount,rightCount,leftRemove,rightRemove - 1);
                }
            }
            
            // 遇到连续相同的括号,更新左右括号出现的次数
            if (cur == '(') {
                leftCount++;
            } else if (cur == ')') {
                rightCount++;
            }

            if (rightCount > leftCount) { // 如果右括号出现次数大于左括号出现次数了,说明配对出错了,直接退出
                break;
            }
        }
    }



    //判断当前字符串是否有效
    //从左往右遍历如果右括号出现次数大于左括号出现次数,那么就是无效的组合
    public boolean isValid(String s) {
        int leftRightCount = 0;

        for (int i = 0;i < s.length();i++) {
            if (s.charAt(i) == '(') { // 遇到左括号,加1
                leftRightCount++;
            } else if (s.charAt(i) == ')') { // 遇到右括号,减1
                leftRightCount--;
                if (leftRightCount < 0) { // 如果右括号出现次数大于左括号出现次数,直接返回false
                    return false;
                }
            }
        }
        return leftRightCount == 0;
    }
}

2.BFS。在进行广度优先搜索时每一轮删除字符串中的1个括号,直到出现合法匹配的字符串为止,此时进行轮转的次数即为最少需要删除括号的个数。进行广度优先搜索时,每次保存上一轮搜索的结果,然后对上一轮已经保存的结果中的每一个字符串尝试所有可能的删除一个括号的方法,然后将保存的结果进行下一轮搜索。在保存结果时,我们可以利用哈希表对上一轮生成的结果去重,从而提高效率。

class Solution {
    public List<String> removeInvalidParentheses(String s) {
        List<String> list = new ArrayList<>();
        Set<String> currentSet = new HashSet<>();

        currentSet.add(s);
        while (true) {
            // 每一次删除一个字符后都判断是否有合法的,如果有,就是删除最少括号的,直接返回此时的list
            for (String str : currentSet) { 
                if (isValid(str)) {
                    list.add(str);
                }
            }

            if (list.size() > 0) {
                return list;
            }

            Set<String> nextSet = new HashSet<>();
            for (String str : currentSet) {
                for (int i = 0;i < str.length();i++) { 
                    if (i > 0 && str.charAt(i) == str.charAt(i - 1)) { // 连续出现一样的括号,选择其中一种情况即可,避免重复
                        continue;
                    }

                    if (str.charAt(i) == '(' || str.charAt(i) == ')') { // 遇到不重复的就删除,然后加入set中
                        nextSet.add(str.substring(0,i) + str.substring(i + 1));
                    }
                }
            }
            currentSet = nextSet;
        }
    }

    //判断当前字符串是否有效
    //从左往右遍历如果右括号出现次数大于左括号出现次数,那么就是无效的组合
    public boolean isValid(String s) {
        int leftRightCount = 0;

        for (int i = 0;i < s.length();i++) {
            if (s.charAt(i) == '(') { // 遇到左括号,加1
                leftRightCount++;
            } else if (s.charAt(i) == ')') { // 遇到右括号,减1
                leftRightCount--;
                if (leftRightCount < 0) { // 如果右括号出现次数大于左括号出现次数,直接返回false
                    return false;
                }
            }
        }
        return leftRightCount == 0;
    }
}

题源:力扣

标签:charAt,括号,int,301,力扣题,leftRemove,++,str
来源: https://blog.csdn.net/xxyneymar/article/details/121989763

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有