题目描述:


Given a string containing just the characters ‘(‘, ‘)’, ‘{‘, ‘}’, ‘[‘ and ‘]’, determine if the input string is valid.

An input string is valid if:

  1. Open brackets must be closed by the same type of brackets.
  2. Open brackets must be closed in the correct order.

Note that an empty string is also considered valid.

input : ()[]{}
output : true

input : ({[]})
output : true

input : ({)}
output : false


简单得说就是括号相匹配,同一个类型的括号连在一起。同一对括号可以嵌套在其他括号中,但只能一对括号都嵌套进去(如({})),不能只嵌套一边的括号(如({)})。

有看过二叉树的前中后序遍历进行加减乘除操作的应该一看到这一题就知道怎么做了。运算中有有括号的先算括号中的数的原则,那么就需要对运算中的括号进行识别与约束,与这道题一个道理。因此一看到这道题就应该想到可以用栈去求解。解法如下:

使用栈(Stack)的解法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
for (Character chara:s.toCharArray()) {
if (chara == '(' || chara == '[' || chara == '{')
stack.push(chara);
else {
if (stack.isEmpty()){
return false;
}else {
Character charPop = stack.pop();
if (charPop == '(' && chara != ')' || charPop == '[' && chara != ']' || charPop == '{' && chara != '}'){
return false;
}
}
}
}
if (stack.isEmpty())
return true;
else
return false;
}
}

思路:所给字符串第一个字符必为”(“,”[“,”{“中的一种,如果不是,那必然无法必配成功,return false。按字符串顺序识别字符将字符串push进栈中。当字符为”)”,”]”,”}”中的一种时,pop一个字符与上面三种字符向匹配,如果匹配成功,继续执行程序,匹配成功的括号自动消除。反之return false,说明这个“右”括号的前面一个括号也是“右”括号,即前面一个括号无法匹配成功。最后判断这个栈是否为空,如果全部都匹配消除完成,栈为空。

优化后的使用栈的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 if (stack.isEmpty() || stack.pop() != c)
return false;
}
return stack.isEmpty();
}

太简洁了!!! 字符如果是“左”括号,那么栈中保存相应的“右”括号。字符如果是“右”括号,与pop出的值相比,如果不相等则说明前一个括号不是相对应的“左”括号,即无法匹配,return false。

除了上面用栈的方法外,还有一种值替换法,实现如下:

目标值替换法

1
2
3
4
5
6
7
8
9
10
11
12
public class Solution {
public boolean isValid(String s) {
int length;

do {
length = s.length();
s = s.replace("()", "").replace("{}", "").replace("[]", "");
} while(length != s.length());

return s.length() == 0;
}
}

思路:暴力替换目标值,符合一整对括号的值直接替换成空值,以替换前的字符串长度和替换后的字符串长度作比较条件,建立循环。最后判断字符串长度是否为零,即整对括号是否被替换完全。

还有Map的方法:

使用Key-Value匹配进行求解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public boolean isValid(String s) {
char[] chars = s.toCharArray();
Map<Character,Character> pairs = new HashMap<Character,Character>();
pairs.put('(', ')');
pairs.put('{', '}');
pairs.put('[', ']');

Stack<Character> stack = new Stack<Character>();
for (char c:chars) {
if (pairs.containsKey(c)) {
stack.push(pairs.get(c));
} else {
if (stack.isEmpty() || c != stack.pop())
return false;
}
}
return stack.isEmpty();
}

思路:将“左”括号作为key,“右”括号作为值放在Map中,其他思路与优化后的使用栈的方法一致。


无论是用栈还是数组还是Hash Map,都只是一种工具,最主要的是思路,有了思路就有了目标,各种存储方法只是帮助达到目标的工具罢了。(当然,有些工具是独轮车,有些工具是飞机哈哈哈哈哈哈哈)