题目
来源:LeetCode.
给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
1.左括号必须用相同类型的右括号闭合。
2.左括号必须以正确的顺序闭合。
示例 1:
输入:s = "()"
输出:true
示例 2:
输入:s = "()[]{}"
输出:true
示例 3:
输入:s = "(]"
输出:false
示例 4:
输入:s = "([)]"
输出:false
示例 5:
输入:s = "{[]}"
输出:true
提示:
- 1 < = s . l e n g t h < = 104 1 <= s.length <= 104 1<=s.length<=104
- s 仅由括号
()[]{}
组成
接下来看一下解题思路:
思路:栈:
遍历给定的字符串
s
s
s。当遇到一个左括号时,期望在后续的遍历中,有一个相同类型的右括号将其闭合,因此我们可以将这个左括号放入栈顶;
当我们遇到一个右括号时,我们需要将一个相同类型的左括号闭合;
此时,我们可以取出栈顶的左括号并判断它们是否是相同类型的括号。如果不是相同的类型,或者栈中并没有左括号,那么字符串
s
s
s 无效,返回
False
\text{False}
False;
在遍历结束后,如果栈中没有左括号,说明我们将字符串
s
s
s 中的所有左括号闭合,返回
True
\text{True}
True,否则返回
False
\text{False}
False;
还可以做一些以下优化:
- 使用哈希表存储每一种括号。哈希表的键为右括号,值为相同类型的左括号;
- 有效字符串的长度一定为偶数,因此如果字符串的长度为奇数,我们可以直接返回 False \text{False} False;
public static boolean isValid(String s) {
if (s == null || (s.length() & 1) == 1) {
return false;
}
Map<Character, Character> map = new HashMap<>();
map.put(')', '(');
map.put(']', '[');
map.put('}', '{');
Stack<Character> stack = new Stack<>();
for (int i = 0; i < s.length(); ++i) {
char c = s.charAt(i);
if (map.containsKey(c)) {
if (stack.isEmpty() || !stack.peek().equals(map.get(c))) {
return false;
}
stack.pop();
} else {
stack.push(c);
}
}
return stack.isEmpty();
}
总结
时间复杂度:
O
(
n
)
O(n)
O(n),其中
n
n
n 是字符串
s
s
s 的长度;
空间复杂度:
O
(
n
+
∣
Σ
∣
)
O(n + |\Sigma|)
O(n+∣Σ∣),其中
Σ
\Sigma
Σ 表示字符集,本题中字符串只包含
6
6
6 种括号,
∣
Σ
∣
=
6
|\Sigma| = 6
∣Σ∣=6。栈中的字符数量为
O
(
n
)
O(n)
O(n),而哈希表使用的空间为
O
(
∣
Σ
∣
)
O(|\Sigma|)
O(∣Σ∣),相加即可得到总空间复杂度;