最直接的想法,存一个map,把左括号和右括号,作为key/value这两类的char储存进去。然后遍历string的时候,check是左括号( map.keySet().contains(ch)) 那就push进stack,如果不是key的话,检查两个条件,1 stack如果为空 return false,2如果不为空,这个时候肯定要pop出来,所以不要用peek了,直接pop,如果不是 key to value的 match,那么就return false
代码:
public class Solution { public boolean isValid(String s) { int len=s.length(); if(len==0) return false; Map<Character, Character> map = new HashMap<Character, Character>(); map.put('(',')'); map.put('{','}'); map.put('[',']'); Stack<Character> stack = new Stack<Character>(); for(char c : s.toCharArray()){ if(map.keySet().contains(c)) stack.push(c); else{ if(stack.isEmpty() || (c!=map.get(stack.pop()))) return false; } } return stack.isEmpty(); } }参考了一个不用map的方法,有两点值得分析:
1,只能把所以各种左括号挨个罗列出来,只有3个的时候还适用
2,把key to value match 键值对应情况,在push进stack的时候就表现出来,直接存入相对应的右括号,这其实相当于上面代码中push进去是 map.get(ch), 所以在遇到右括号时就不用再去使用get()方法了,这两种选择再有map的时候都一样,但是当没有map的时候,还是后者更加省事,省去再去挨个罗列情况的过程。
!但是,从更加generalize的角度来说,用map来记录左右对应关系更加适用,如果有K=100种左括号右括号的对应关系,挨个罗列情况就变得非常不切实际。
代码如下:
public class Solution { public boolean isValid(String s) { Stack<Character> stack = new Stack<Character>(); for(char c: s.toCharArray()){ if(c=='(') stack.push(')'); else if(c=='[') stack.push(']'); else if(c=='{') stack.push('}'); else{ // 包括了右括号的三种情况,然后再在里面判断,而且写得极为简练,省略了很多redundant的东西 if(stack.isEmpty() || c!=stack.pop()) return false; // empty就return,如果没有empty,那么就直接pop进行对比,而不是peek()检查后,如果相等在pop,直接合并成一步,这是熟练之后的写法,何不是面试时的重点,不要求扣这么细 优化到这么细,写清楚更好 } } return stack.isEmpty(); } }过了几天我又看到这题,又写了一遍,尝试这不用map记录,直接罗列3种情况,看来之前写的总结还是会忘的,忘了之后居然退化到了最直白的代码,哈哈汗啊
public class Solution { public boolean isValid(String s) { int len=s.length(); if(len==0) return false; Stack<Character> stack = new Stack<>(); for(char ch: s.toCharArray()){ if(ch=='(' || ch=='{' || ch=='[') stack.push(ch); else if( ((ch==')')&& (!stack.isEmpty())&& stack.peek()=='(') || ((ch==']')&& (!stack.isEmpty())&& stack.peek()=='[') || ((ch=='}')&& (!stack.isEmpty())&& stack.peek()=='{') ) stack.pop(); else return false; } return stack.isEmpty(); } } //注意:在stack.peek()之前要check stack是否为空,使用isEmpty() 不是 empty().卧槽,简直太navie了,上面有那么明显的重复代码 !stack.isEmpty() 居然不知道优化,唉真是naive,真是被动学习记忆,而不是有一个主动优化的意识,缺少了年轻时的那种表现的欲望,不会抓住甚至去挖掘表现自己的机会了。。总结来说,简单一句话,用stack记录,如果左括号就压入,如果右括号,1,是空stack return false,2,非空,但是pop出来的不能match 也return false。最后检查stack是否为空。
