Java 算法:括号问题

括号生成

1. LeetCode. 22. 括号生成

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

示例 1:

输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]

示例 2:

输入:n = 1
输出:["()"]
class Solution {
    public List<String> generateParenthesis(int n) {
        List<String> ans = new ArrayList<>();
        if(n == 0){
            return ans;
        }
        backtrack(ans, n, new StringBuilder(), 0, 0);
        return ans;
    }

    public void backtrack(List<String> ans, int n, StringBuilder sb, int open, int close){
       // 左括号数量不大于 n,可以放一个左括号。如果右括号数量小于左括号的数量,可以放一个右括号
        if(open>n || close>open){
            return; // return才能继续查找下一个
        }
        if(sb.length() == 2*n){
            ans.add(sb.toString());
            // return;	可有可无
        }
        sb.append("(");
        backtrack(ans, n, sb, open+1, close);
        // 回溯
        sb.deleteCharAt(sb.length()-1);
        
        sb.append(")");
        backtrack(ans, n, sb, open, close+1);
        sb.deleteCharAt(sb.length()-1);
    }
}

2. LeetCode. 20. 有效的括号

给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。

有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。

示例 1:

输入:s = "()"
输出:true

示例 2:

输入:s = "(]"
输出:false

示例 4:

输入:s = "([)]"
输出:false
class Solution {
    public boolean isValid(String s) {
        int len = s.length();
        // !!!字符串长度是奇数之间判错
        if(len%2 == 1){
            return false;
        }
        // 借助Map找对应关系,更方便
        Map<Character,Character> map = new HashMap<>();
        
        map.put('(', ')');
        map.put('[', ']');
        map.put('{', '}');
        Stack<Character> stack = new Stack<>();
        
        for(int i = 0; i < len; i++){
            if(s.charAt(i)=='(' || s.charAt(i)=='[' || s.charAt(i)=='{'){
                stack.push(s.charAt(i));
            }else{
                if(!stack.isEmpty()){
                    char open = stack.pop();
                    if(map.get(open) != s.charAt(i)){
                        return false;
                    }
                }else{
                    return false;
                }
            }
        }
        return stack.isEmpty();
    }
}

3. LeetCode. 301. 删除无效的括号

给你一个由若干括号和字母组成的字符串 s ,删除最小数量的无效括号,使得输入的字符串有效。
返回所有可能的结果。答案可以按 任意顺序 返回。

示例 1:

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

示例 2:

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

示例 3:

输入:s = ")("
输出:[""]
class Solution {
    List<String> ans = new ArrayList<>();

    public List<String> removeInvalidParentheses(String s) {
        int len = s.length();
        int lremove = 0;
        int rremove = 0;
        for(int i = 0; i < len; i++){
            if(s.charAt(i) == '('){
                lremove++;
            }else if(s.charAt(i)==')'){
                if(lremove!=0){
                    lremove--;
                }else{
                    rremove++;
                }
            }
        }
        backtrack(s, 0, lremove, rremove);
        return ans;
    }

    public void backtrack(String s, int start, int lremove, int rremove){
        if(lremove==0 && rremove==0){
            if(isValid(s)){
                ans.add(s);
            }
            return;
        }
        for(int i = start; i < s.length(); i++){
            // 去重,在每次进行搜索时,如果遇到连续相同的括号只需要搜索一次即可
            if(i>start && s.charAt(i)==s.charAt(i-1)){
                continue;
            }
            // 剪枝,如果剩余的字符无法满足去掉的数量要求,直接返回
            if(lremove+rremove > s.length()-i){
                return;
            }
            if(lremove>0 && s.charAt(i) == '('){
                backtrack(s.substring(0,i)+s.substring(i+1), i, lremove-1, rremove);
            }
            if(rremove>0 && s.charAt(i) == ')'){
                backtrack(s.substring(0,i)+s.substring(i+1), i, lremove, rremove-1);
            }
        }
    }

    public boolean isValid(String s){
        int len = s.length();
        int countLeft = 0;
        for(int i = 0; i < len; i++){
            if(s.charAt(i) == '('){
                countLeft++;
            }else if(s.charAt(i) == ')'){
                countLeft--;
                // 不要忘记下面的判断,否则出现"()())("结果
                if(countLeft < 0){
                    return false;
                }
            }
        }
        return countLeft==0;
    }
}

4. LeetCode. 32. 最长有效括号

给你一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长有效(格式正确且连续)括号子串的长度。

示例 1:

输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"

示例 2:

输入:s = ")()())"
输出:4
解释:最长有效括号子串是 "()()"

示例 3:

输入:s = ""
输出:0
class Solution {
    public int longestValidParentheses(String s) {
        int ans = 0;
        int len = s.length();
        // 为了处理边界,始终保持[栈底元素]为当前已经遍历过的元素中[最后一个没有被匹配的右括号的下标]
        Stack<Integer> stack = new Stack<>();
        // 为了满足栈底为[最后一个没有被匹配的右括号的下标],一开始的时候就放入值为-1的元素
        stack.push(-1);
        for(int i = 0; i < len; i++){
            if(s.charAt(i) == '('){
                stack.push(i);
            }else if(s.charAt(i)==')'){
                stack.pop();
                // 如果栈为空,说明当前的右括号是没有被匹配的右括号,将其下标放入栈中来更新之前提到的[最后一个没有被匹配的右括号的下标]
                if(stack.isEmpty()){
                    stack.push(i);
                }else{
                    ans = Math.max(ans, i-stack.peek());
                }
            }
        }
        return ans;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值