Java解决括号匹配算法问题

Wesley13
• 阅读 675

有效字符串需满足:

左括号必须用相同类型的右括号闭合。包括:“( )”,“[ ]”,“{ }”。 左括号必须以正确的顺序闭合。 注意空字符串可被认为是有效字符串。

思路:在这里我们使用栈来实现。遍历字符串时判断:如果是左括号,那么我们将其入栈;如果为右括号,我们先判断栈是否为空(有可能字符串刚开始就是一个右括号呢),为空的话直接返回false,不为空时判断:栈顶元素和下一个要入栈的元素是否相匹配,若匹配就出栈元素,若不匹配,返回false。

又因括号种类比较多,且存在${}这种括号不是单个字符的问题, 所以引入双向map,增强其扩展性。

代码如下:

import org.apache.commons.collections4.BidiMap;
import org.apache.commons.collections4.bidimap.DualHashBidiMap;
import org.junit.Assert;
import org.junit.Test;

import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

/**
 * @author : 杨松<yangsong158@qq.com>
 * @date : 2020/4/3
 * @desc :
 */
public class BracketPairTest {

    public boolean pairCheck(Map<String,String> pairMap,String expr) {
        if (expr == null || expr == "") throw new NullPointerException("表达式为空");
        //双向Map解决括号匹配问题
        BidiMap<String,String> bracketMap = new DualHashBidiMap();
        bracketMap.putAll(pairMap);

        Stack<String> stack = new Stack<String>();

        StringBuffer overlap = new StringBuffer();  //叠加器,解决括号不为一个字符的问题
        int overlapMaxLen = 2;                      //叠加器,最大叠加字符数
        for (int i = 0; i < expr.length(); i++) {
            String word = expr.substring(i,i+1);
            overlap.append(word);
            String overlapWord = overlap.toString();
            if(bracketMap.containsKey(word)){
                stack.push(word);
            }else if(bracketMap.containsKey(overlapWord)){
                stack.push(overlapWord);
            }else{
                if(bracketMap.containsValue(word)){             //右半部分括号
                    String left = bracketMap.getKey(word);      //找左半部分括号
                    if (!stack.empty() && stack.peek().equals(left)) {  //栈顶元素和括号对中的左半括号相同,则匹配,出栈
                        stack.pop();
                    }
                }else if(bracketMap.containsValue(overlapWord)){ //单独处理下叠加器中涉及括号有多个字符的问题
                    String left = bracketMap.getKey(overlapWord);
                    if (!stack.empty() && stack.peek().equals(left)) {
                        stack.pop();
                    }
                }
            }
            //叠加器超过满最大个数,清空最前面的字符
            if(overlap.length()==overlapMaxLen) overlap.deleteCharAt(0);
        }

        if (stack.empty())
            return true;
        return false;
    }

    @Test
    public void pairCheckTest(){
        //1.设置括号对
        Map<String,String> bracketMap = new HashMap(){{
            put("{", "}");
            put("[", "]");
            put("(", ")");
            put("<$", ">");
            put("【※", "※】");
        }};
        //2.验证是否通过
        Assert.assertTrue(pairCheck(bracketMap,"()"));
        Assert.assertTrue(pairCheck(bracketMap,"()[]"));
        Assert.assertTrue(pairCheck(bracketMap,"()[]{}"));
        Assert.assertTrue(pairCheck(bracketMap,"{[]}"));
        Assert.assertTrue(pairCheck(bracketMap,"{[()]}"));
        Assert.assertTrue(pairCheck(bracketMap,"{((1+3)+2+4)+9*7}"));
        Assert.assertTrue( pairCheck(bracketMap,"{[(<$这是一段内容>)]}"));
        Assert.assertFalse(pairCheck(bracketMap,"{[(<$这是一段内容)]}"));
        Assert.assertTrue(pairCheck(bracketMap,"{[(【※变量测试※】)]}"));
        Assert.assertFalse(pairCheck(bracketMap,"{[(【※变量测试】)]}"));
    }

}
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
java实现判断两个二叉树是否相同
1、定义树节点类:节点值、左节点、右节点、构造器2、先判断树是否为空的情况3、树不为空时,判断节点所指的值是否相等,若相等,则递归判断节点的左右节点是否相同,相同则返回true/\\ \Definitionforbinarytree \publicclassTreeNode{ \    intval
Easter79 Easter79
3年前
SpringBoot自定义序列化的使用方式
场景及需求:项目接入了SpringBoot开发,现在需求是服务端接口返回的字段如果为空,那么自动转为空字符串。例如:\    {        "id":1,        "name":null    },    {        "id":2,        "name":"x
Wesley13 Wesley13
3年前
%5B0%5D表示什么意思
students%5B0%5D表示:students\0\%5B为左中括号\%5D为右中括号\这样就明白了varqsrequire('qs');varobj{name:'Tom',description:'hello',hobbies:'basketball
Stella981 Stella981
3年前
SpringBoot自定义序列化的使用方式
场景及需求:项目接入了SpringBoot开发,现在需求是服务端接口返回的字段如果为空,那么自动转为空字符串。例如:\    {        "id":1,        "name":null    },    {        "id":2,        "name":"x
Wesley13 Wesley13
3年前
20165322 第一周结队编程
结队编程四则运算阶段总结学习笔记中缀表达式转换为后缀表达式如果遇到数字,我们就直接将其输出。如果遇到非数字时,若栈为空或者该符号为左括号或者栈顶元素为括号,直接入栈。如果遇到一个右括号,持续出栈并输出符号
Wesley13 Wesley13
3年前
ACM_括号匹配
括号匹配(栈)TimeLimit:2000/1000ms(Java/Others)ProblemDescription:给一组包含()两种括号的序列,检查是否是合法的。如:(),(
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_