算法通关村—括号匹配问题解析

文章介绍了如何使用栈解决有效括号的问题,包括两种方法:一种利用HashMap存储括号对应关系,另一种直接用栈处理;同时讲解了最长有效括号问题的栈实现,通过维护一个存储左括号位置的栈来找到最长的连续有效括号子串。文章还提到了这两种方法的时间和空间复杂度,并列举了相关的括号类问题。
摘要由CSDN通过智能技术生成

1. 有效的括号

给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。
示例 1:
输入:s = “()”
输出:true

20. 有效的括号

1.1 HashMap+栈

将左括号作为key,右括号作为value,然后存入map集合里面去,只有当当前字符是左括号时候,才会让其进入,否则就是右括号,然后将当前栈顶元素弹出,找到对应的右括号,然后比对两个括号是否一致。

 public static boolean isValid(String s) {
        if (s.length() <= 1) return false;
        // 将左括号作为key,右括号作为value
        HashMap<Character, Character> map = new HashMap<>();
        map.put('{', '}');
        map.put('[', ']');
        map.put('(', ')');
        // 栈记录左括号
        Stack<Character> stack = new Stack<>();
        for (int i = 0; i < s.length(); i++) {
            char currChar = s.charAt(i);
            // 左括号
            if (map.containsKey(currChar)) {
                // 左括号入栈
                stack.push(currChar);
            } else {
                // 右括号
                if (!stack.isEmpty()) {
                    // 栈顶元素对应左括号
                    Character leftCharKey = stack.pop();
                    // 找到对应右括号
                    Character rightChar = map.get(leftCharKey);
                    // 右括号不等于当前括号
                    if (rightChar != currChar) {
                        return false;
                    }
                    // 栈为空,表示没左括号进入
                } else {
                    return false;
                }
            }
        }
        return stack.isEmpty();
    }

在这里插入图片描述
时间复杂度:O(n) 将字符串遍历找到左括号存入,而map的查找元素时间复杂度是O(1)

空间复杂度:map的空间复杂度是O(1),栈出去元素时间复杂度O(n/2),因为只是存入了左括号。

1.2 栈优化

可以看出,第一种方法主要是使用map来进行查找存储括号,但是由于题目已知相应的括号,那么可以稍微简化一下,我只需要判断当前字符是不是左括号,是左括号,然后将对应的右括号添加栈,如果是右括号,就比对当前括号是不是一致。

 public boolean isValid(String s) {
      Stack<Character> stack = new Stack<>();
      for(int i=0;i<s.length();i++){
          char currChar = s.charAt(i);
          if(currChar == '['){
              stack.push(']');
          }else if(currChar == '{'){
              stack.push('}');
          }else if(currChar == '('){
              stack.push(')');
          }else{
              // 右括号
              if(stack.isEmpty() || stack.pop() != currChar){
                  return  false;
              }
          }
      }
      return stack.isEmpty();
    }

在这里插入图片描述
不过这个方法只适用于少量数据括号,数据量多了,还是要使用map存储。

2. 最长有效括号

32. 最长有效括号

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

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

2.1 栈

  1. 如果出现’(',保留当前下标
  2. 出现’)',先弹出栈顶元素,默认这两个括号是一对,此时长度就是右括号的下标减去左括号的下标
  3. 判断是否栈为空,为空就要把当前右括号重新放入栈里面,原因是没有找到匹配的左括号
public int longestValidParentheses(String s) {
        Stack<Integer> stack = new Stack<>();
        int maxLen =0;
        stack.push(-1);
        for(int i= 0;i<s.length();i++){
            char currChar = s.charAt(i);
            if(currChar == '(' ){
                stack.push(i);
            }else {
                stack.pop();
                if(stack.isEmpty() ){
                   stack.push(i);
                }else{
                    maxLen = Math.max(maxLen,i-stack.peek());
                }
            }
        }
        return maxLen;
    }

在这里插入图片描述

时间复杂度:O(n)
空间复杂度:O(n)

总结:这一题使用栈代码看起来简单,但是实际做的时候发现,比较难以考虑到一些边界值以及将下标放入栈里面去。

3. 类似题目

Leetcode20 有效的括号、LeetCode22 .括号生成、LeetCode32.最长有效括号、LeetCode301.删除无效的括号和leetcode 856 括号的分数等。

后面几题都涉及到了动态规划等等,之后再做。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

flybase

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值