问题链接:https://oj.leetcode.com/problems/valid-parentheses/
问题描述:
Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.
The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "([)]" are not.
问题API:public boolean isValid(String s)
问题分析:
这题本身并不难,其实就是一个状态机的题目,弄清楚每个状态需要做的事情就很容易了。
实际上就两类状态:
状态一:‘{’ '[' '(',这个需要进行压栈遇到的字符。
状态二:'}, ']', ')', 这个时候需要进行Pop栈,看看pop出来的字符是否能够匹配当前的状态字符。
这题并不是很难,时间O(n),空间O(n)。但实际上在网上流传了很多的一个错误答案,这个错误答案曾经是可以过leetcode oj的(我就模仿过)。这个方法试图将空间缩小到O(1),利用的是计数器,我先贴出来这个方法的代码,大家参考一下就好,不要学习,实际上是不对的:
public boolean isValid(String s) {
int big = 0, mid = 0, small = 0;
for(int i = 0; i < s.length(); i++){
if(s.charAt(i) == '('){
if(i < s.length() - 1 && (s.charAt(i + 1) == ']' || s.charAt(i + 1) == '}')){
return false;
}
small++;
}
if(s.charAt(i) == '['){
if(i < s.length() - 1 && (s.charAt(i + 1) == ')' || s.charAt(i + 1) == '}')){
return false;
}
mid++;
}
if(s.charAt(i) == '{'){
if(i < s.length() - 1 && (s.charAt(i + 1) == ']' || s.charAt(i + 1) == ')')){
return false;
}
big++;
}
if(s.charAt(i) == ')'){
small--;
}
if(s.charAt(i) == ']'){
mid--;
}
if(s.charAt(i) == '}'){
big--;
}
}
if(small != 0 || mid != 0 || big != 0)
return false;
return true;
}
这个方法在两个月前还能够过leetcode oj,但现在加了一个新case就过不了了。是因为本质上这个方法就不对。
Stack目前在我看来是必须的。所以给出代码如下:
public boolean isValid(String s) {
Stack<Character> char_stack = new Stack<Character>();
for(int i = 0; i < s.length(); i++){
char c = s.charAt(i);
switch(c){
case '{':
char_stack.push(c);
break;
case '}':
if(char_stack.isEmpty() || char_stack.pop() != '{')
return false;
break;
case '[':
char_stack.push(c);
break;
case ']':
if(char_stack.isEmpty() || char_stack.pop() != '[')
return false;
break;
case '(':
char_stack.push(c);
break;
case ')':
if(char_stack.isEmpty() || char_stack.pop() != '(')
return false;
break;
default:
break;
}
}
return char_stack.isEmpty();
}
最后只需要判断栈里的字符元素是否被弹空即可。另外状态机的题目我还是比较推荐switch case的做法的,这比较符合状态机的定义。