【问题描述】
一个合法的括号串,是指只包含括号的串,如果满足如下条件:
(1)<> () [] {} 这四对括号是合法的;
(2)如果r是合法括号串,则<r> (r) [r] {r}也是;
(3)如果r,s是合法括号串,则rs也是;
所以<<>> , [<>{}(())],[({<>})]是合法的括号串,而)(,[( ])就不是。
【输入形式】
输入第一行正整数t (10 ≤ n ≤ 100),表示有多少组测试数据。
后面有t行,每行一个只包含8种括号符号的括号串。
40%的括号串的长度L 2 ≤ L≤ 20;
30%的括号串的长度L 2 ≤ L≤ 200;
20%的括号串的长度L 2 ≤ L≤ 2000;
10%的括号串的长度L 2 ≤ L≤ 20000;
【输出形式】
对于每组测试数据,如果括号串是合法的,输出“Yes”(输出没有引号)占一行,否则,输出“No”(输出没有引号)占一行。
【样例输入】
6
<<>>
)(
[<>{}(())]
[({<>})]
[(])
<([{
【样例输出】
Yes
No
Yes
Yes
No
No
解题思路
数据结构:栈
基本思路:遍历括号串,当遇到左括号时将其压入栈,遇到右括号时尝试从栈中弹出一个元素,并检查弹出的括号是否与当前的右括号匹配。如果在任何时候遇到不匹配的情况,或者在遍历完整个括号串后栈不为空,则该括号串不是合法的。
解题步骤:
-
初始化栈:用来存放遇到的左括号
-
遍历括号串:对每个字符进行检
-
如果是左括号,将其压入栈
-
如果是右括号,检查栈是否为空,若为空,则直接判定为非法。若不为空,则弹出栈顶元素,检查是否与当前右括号匹配
-
-
匹配检查:可以通过一个辅助的方法或者映射来实现
-
最终检查:遍历完毕后,检查栈是否为空。如果为空,合法;否则,不合法
Java代码
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Stack;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int t = scanner.nextInt();
scanner.nextLine(); // 跳过行尾的换行符
while(t-- > 0){ // t--错误
String s = scanner.nextLine();
System.out.println(isValid(s) ? "Yes" : "No");
}
scanner.close();
}
private static boolean isValid(String s) {
// 初始化括号匹配关系
Map<Character, Character> mappings = new HashMap<>();
mappings.put('>','<'); //右括号作为键,左括号作为值,如果将右括号作为键,1. 使用HashMap的get方法来快速查找对应的左括号;2. 在遍历字符串时,检查当前字符是否为HashMap中的一个键来判断是否是右括号;3. 判断栈是否为空
mappings.put(')','(');
mappings.put(']','[');
mappings.put('}','{');
//判断方式
Stack<Character> stack = new Stack<>();
for (char c : s.toCharArray()) { //.toCharArray()字符串转换为字符数组
// 如果是右括号
if(mappings.containsKey(c)){ //.containsKey(c)
char topElem = stack.isEmpty() ? '#' : stack.pop(); // 弹出栈顶元素进行匹配,如果栈为空,用一个不可能匹配的值代替
if(topElem != mappings.get(c)) return false;
}
else stack.push(c); // 如果是左括号,压入栈中
}
return stack.isEmpty(); // 如果栈为空,说明括号完全匹配
}
}