最直接的想法,存一个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是否为空。