Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.
An input string is valid if:
Open brackets must be closed by the same type of brackets.
Open brackets must be closed in the correct order.
Note that an empty string is also considered valid.
Example 1:
Input: "()"
Output: true
Example 2:
Input: "()[]{}"
Output: true
Example 3:
Input: "(]"
Output: false
Example 4:
Input: "([)]"
Output: false
Example 5:
Input: "{[]}"
Output: true
这道题目的意思就是括号匹配,如果所有的括号都完全匹配,则返回true
,否则返回false
。
我的思路:
选择了栈这种数据结构,因为栈的特点就是先进后出,所以我可以将字符串里的所有括号入栈,在入栈的过程中,来判断是否完全匹配。
具体做法:
- 第一个元素入栈,第二个元素入栈之前判断一下,是否和第一个元素刚好配对,
- 如果是则把已经入栈的那个元素弹出栈并从栈中移除;否则,就把该元素继续入栈
- 循环一次字符串。
- 如果所有括号都完全配对,那么最后栈就没有任何元素,否则,栈中是存在元素的
- 在进行1之前,还需要做个判断,因为括号是成对出现,如果字符串的长度为奇数,那么该字符串的所有括号一定不会是完全匹配。
此处涉及到数据结构栈,需要了解一下:
- 栈的特点:先进后出
pop()
方法,将栈顶元素弹出并从栈中移除掉peek()
方法,将栈顶元素弹出,但是并不从栈中移除该元素isEmpty()
方法,判断栈中是否存在元素。
下面是我的实现代码:
class Solution {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<Character>();
if (s.length() % 2 == 1) {
return false;
} else {
stack = new Stack<Character>();
for (int i = 0; i < s.length(); i++) {
if (stack.isEmpty()) {
stack.push(s.charAt(i)); // 当前栈是空的 存入当前位置的字符
} else if ((stack.peek() == '[' && s.charAt(i) == ']')||
(stack.peek() == '(' && s.charAt(i) == ')')||
(stack.peek() == '{' && s.charAt(i) == '}')
) {
stack.pop();
} else {
stack.push(s.charAt(i));
}
}
if (stack.isEmpty()) {
return true;
} else {
return false;
}
}
}
}
Runtime: 2 ms, faster than 97.78% of Java online submissions for Valid Parentheses.
Memory Usage: 35.7 MB, less than 36.72% of Java online submissions for Valid Parentheses.
Next challenges
看了一下discuss中其他的解法,找了几个看看:
code1:
- 先将配对的元素都以
key-value
的形式存储到map
中 - 创建一个队列,队列的特定就是先进先出
- 循环字符串,首先判断
map
中是否包含该key
, - 如果包含,再次判断队列是否为空,
- 如果队列不为空,判断队列的末尾元素是否和这个
key
所对应的value
字符相等。 - 如果相等,就把这个队列的最后一个元素移除掉,否则这个元素入队列。
class Solution {
public boolean isValid(String s) {
Map<Character, Character> p = new HashMap<Character, Character>(){{
put(')','(');
put(']','[');
put('}','{');
}};
Deque stack = new LinkedList<>();
for (Character c: s.toCharArray()){
if (p.containsKey(c) && !stack.isEmpty() && stack.getLast()==p.get(c)){
stack.removeLast();
}else{
stack.add(c);
}
}
return stack.isEmpty();
}
}
Runtime: 2 ms, faster than 97.78% of Java online submissions for Valid Parentheses.
Memory Usage: 36.5 MB, less than 36.11% of Java online submissions for Valid Parentheses.
此处特别说明一下getLast()
和removeLast()
方法及为什么使用LinkedList
。
getLast()
:是Deque
接口中的一个方法,检索但不删除此双端队列的最后一个元素。
这种方法与peekLast
的区别仅在于:它如果此双端队列为空,则抛出异常。
removeLast()
:是Deque
接口中的一个方法,检索但删除此双端队列的最后一个元素。
这种方法与pollLast
的区别仅在于:它如果此双端队列为空,则抛出异常。
再看一种解法,也是利用栈,只是思路不同:
class Solution {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
for(int i = 0; i < s.length(); i++) {
char a = s.charAt(i);
if(a == '(' || a == '[' || a == '{'){
stack.push(a);
} else if(stack.empty()){
return false;
} else if(a == ')' && stack.pop() != '('){
return false;
} else if(a == ']' && stack.pop() != '['){
return false;
}else if(a == '}' && stack.pop() != '{'){
return false;
}
}
return stack.empty();
}
}