LeetCode 20.有效的符号算法解析及栈的相关知识
LeetCode 20.有效的符号解析及栈的相关知识(Java实现)
20.有效的符号
题目要求:
给定一个只包括’(‘,’)‘,’{‘,’}‘,’[‘,’]'的字符串s,判断字符串是否有效。
有效字符串需满足:
1.左括号必须使用相同类型的右括号闭合
2.左括号必须以正确的顺序闭合
3,每个右括号都有一个相同类型的左括号。
示例1:
输入: s=“()”
输出:true
示例2:
输入:s=“(){}[]”
输出:true
示例3:
输入:s=“({]})”
输出:false
示例4:
输入:s=“({[]})”
输出:true
示例:
输入:s=")”
通过以上案例首先我们发现的一个规律是字符串长度必须是偶数,要求成对出现;
第二个规律是如果一个字符是符合规律的,必有左右两个括号;它其中若存在元素,必须也符合该规律
第三个规律是有效的字符串,右括号必然存在上一个元素是左括号或者去除中间元素后的,上一个元素是左括号
通过以上分析,我们需要一个后进先出的数据结构存储数据,栈就非常符合我们的需求,当满足条件时就从栈中移除出去。另外还需要一个hashMap来存储括号对应的值,由于使用栈建议key为括号,value为左括号。
Java中定义栈
- Stack
Java提供一个Stack对象直接通过new就可以创建一个stack,stack底层是继承一个Vector,所以它是线程安全的类,但是它并不遵循先进后出的原则,只是一个平常顺序。而且底层使用synchronized 性能比较低(不推荐)
Stack<String> stack1 = new Stack<>();stack1.push("123");stack1.push("234");
2.Deque
deque是一种继承Queue的接口,有众多的实现类,比如ArrayDeque、LinkedBlockingDeque、LinkedDeque还有LinkedList也实现了deque。所以对于出栈、入栈的操作,LiinkedList比较合适,Node插入和删除速度快。
算法实现
private boolean isValid(String str){int length=str.length();String regex = "^[(){}\\[\\]]+$";//正则表达式,校验字符串中是否只有()[]{}Pattern pattern = Pattern.compile(regex);Matcher matcher = pattern.matcher(str);if(!matcher.matches()||length%2==1){//字符串中有其他字符或者长度为奇数直接返回falsereturn false;}//定义匹配的mapMap<Character,Character> map=new HashMap<>();map.put(')','(');map.put('}','{');map.put(']','[');Deque<Character> stack=new LinkedList<>();//创建一个栈//循环字符串的字符,如果map中存在则在栈中查找对应左括号,不存在返回false,存在移除栈顶元素;map不存在压入栈中for(int i=0;i<length;i++){char charAt = str.charAt(i);//获取当前元素if(map.containsKey(charAt)){//如果map中包含改keyif(stack.isEmpty()||stack.peek()!=map.get(charAt)){//stack是空的或者栈中的第一个元素的值不等于map中的起始括号,stack.peek()获取栈中第一个元素,0号位的元素return false;}stack.pop();//出栈}else{stack.push(charAt);//入栈,比如字符是(就入栈,遵循先进后出的原则}}Stack<Integer> stack1 = new Stack<>();return stack.isEmpty();}
代码解析
例1:s=“({[})”
按照循环和栈的规则,({[都将push到栈中,按照先进后出的原则,顺序为0:[,1:{,2:(;当循环到字符},获取前括号为{,比较栈顶元素,不相等直接返回false
例2:s=“({[]})”
({[会采用先进后出的顺序压入栈中,0号位栈顶元素为[;当循环到字符]时,满足stack.peek()==[,之后[会出栈,{变为0号位的值;}字符类似以上操作
以上代码时间复杂度是O(n),n是字符串的长度。并且使用长度和正则表达式校验,会节省更多时间。
测试结果
@Testpublic void testFormat(){String str="({[]})";boolean valid = isValid(str);System.out.println(valid?"格式正确!":"格式不正确!");}
测试1:
输入:str=“({[]})”
输出:格式正确
测试2:
输入:str=“()”
输出:格式正确
测试3:
输入:s=“({]})”
输出:格式不正确
测试4:
输入:s=“[1]”
输出:格式不正确