Java中的平衡括号算法
1. 概述
平衡括号,也称为平衡括号,是一个常见的编程问题。
在本教程中,我们将验证给定字符串中的括号是否平衡。
这种类型的字符串是所谓的Dyck 语言 的一部分。
2. 问题陈述
括号被认为是以下任何字符——“(“, “)”, “[”, “]”, “{“, “}”。
如果左括号“(”、“[”和“{”出现在相应的右括号“)”、“]”和“}”的左侧,则一组括号被认为是一对。
但是,如果包含的括号组不匹配,则包含括号对的字符串是不平衡的。
类似地,包含非括号字符(如 az、AZ、0-9)或其他特殊字符(如 #、$、@ )的字符串也被认为是不平衡的。
例如,如果输入是“{[(])}”,则一对方括号“[]”包含一个不平衡的左圆括号“(”。类似地,一对圆括号“() ”,包含一个不平衡的右方括号“]”。因此,输入字符串“{[(])}”是不平衡的。
因此,如果满足以下条件,则称包含括号字符的字符串是平衡的:
- 匹配的左括号出现在每个相应的右括号的左侧
- 平衡括号内的括号也是平衡的
- 它不包含任何非括号字符
有几个特殊情况需要记住:null被认为是不平衡的,而空字符串被认为是平衡的。
为了进一步说明我们对平衡括号的定义,让我们看一些平衡括号的例子:
()
[()]
{[()]}
([{{[(())]}}])
还有一些不平衡的:
/a/b/c/[/]/(/)/{/}/
/{/{/[/]/(/)/}/}/}/}/
{[(])}
现在我们对我们的问题有了更好的理解,让我们看看如何解决它!
3. 解决方法
有不同的方法可以解决这个问题。在本教程中,我们将研究两种方法:
- 使用String类的方法
- 使用双端队列实现
4. 基本设置和验证
让我们首先创建一个方法,如果输入平衡则返回true,如果输入不平衡则返回false:
public boolean isBalanced(String str)
让我们考虑输入字符串的基本验证:
- 如果传递了一个null输入,那么它是不平衡的。
- 对于要平衡的字符串,左括号和右括号应该匹配。因此,可以肯定地说,长度为奇数的输入字符串不会被平衡,因为它将包含至少一个不匹配的括号。
- 根据问题陈述,应在括号内检查平衡行为。因此,任何包含非括号字符的输入字符串都是不平衡字符串。
鉴于这些规则,我们可以实现验证:
if (null == str || ((str.length() % 2) != 0)) {
return false;
} else {
char[] ch = str.toCharArray();
for (char c : ch) {
if (!(c == '{' || c == '[' || c == '(' || c == '}' || c == ']' || c == ')')) {
return false;
}
}
}
现在输入字符串已经过验证,我们可以继续解决这个问题。
5. 使用String.replaceAll方法
在这种方法中,我们将遍历输入字符串,使用*String.replaceAll 从字符串中删除出现的“()”、“[]”和“{}” 。*我们继续这个过程,直到在输入字符串中找不到更多的匹配项。
一旦该过程完成,如果我们的字符串的长度为零,则所有匹配的括号对都已被删除,并且输入字符串是平衡的。但是,如果长度不为零,则字符串中仍然存在一些不匹配的左括号或右括号。因此,输入字符串是不平衡的。
让我们看看完整的实现:
while (str.contains("()") || str.contains("[]") || str.contains("{}")) {
str = str.replaceAll("\\(\\)", "")
.replaceAll("\\[\\]", "")
.replaceAll("\\{\\}", "");
}
return (str.length() == 0);
6. 使用Deque
Deque 是 Queue 的一种形式,在Queue的两端提供了 add、retrieve 和 peek 操作。我们将利用此数据结构的后进先出 (LIFO) 顺序功能来检查输入字符串中的余额。
首先,让我们构建我们的Deque:
Deque<Character> deque = new LinkedList<>();
请注意,我们在这里使用了LinkedList ,因为它提供了Deque接口的实现。
现在我们的双端队列已经构建好了,我们将一个一个地遍历输入字符串的每个字符。如果字符是一个左括号,那么我们将它添加为Deque中的第一个元素:
if (ch == '{' || ch == '[' || ch == '(') {
deque.addFirst(ch);
}
但是,如果字符是右括号,那么我们将对LinkedList执行一些检查。
首先,我们检查LinkedList是否为空。空列表意味着右括号不匹配。因此,输入字符串是不平衡的。所以我们返回false。
但是,如果LinkedList不为空,则我们使用peekFirst方法查看其最后一个字符。如果它可以与右括号配对,那么我们使用removeFirst方法从list中删除这个最上面的字符并继续循环的下一次迭代:
if (!deque.isEmpty()
&& ((deque.peekFirst() == '{' && ch == '}')
|| (deque.peekFirst() == '[' && ch == ']')
|| (deque.peekFirst() == '(' && ch == ')'))) {
deque.removeFirst();
} else {
return false;
}
在循环结束时,所有字符都经过平衡检查,因此我们可以返回true。下面是基于Deque的方法的完整实现:
Deque<Character> deque = new LinkedList<>();
for (char ch: str.toCharArray()) {
if (ch == '{' || ch == '[' || ch == '(') {
deque.addFirst(ch);
} else {
if (!deque.isEmpty()
&& ((deque.peekFirst() == '{' && ch == '}')
|| (deque.peekFirst() == '[' && ch == ']')
|| (deque.peekFirst() == '(' && ch == ')'))) {
deque.removeFirst();
} else {
return false;
}
}
}
return deque.isEmpty();