堆栈如何非常重要的经典例子是验证一串括号是否平衡的问题。你从一个空堆栈开始,你继续推送/弹出堆栈中的元素,最后,检查你的堆栈是否为空,如果是,则返回该字符串确实是平衡的。
但是,我正在寻找其他效率较低的方法来解决此问题。我想通过首先提出解决问题的指数/非线性算法向我的学生展示堆栈数据结构的有用性,然后介绍堆栈解决方案。是否有人熟悉除基于堆栈的方法之外的其他方法?
答案 0 :(得分:2)
找到最后一个开头 - 括号,看它是否关闭,以及后面是否没有其他类型的括号。 如果是,请重复此过程,直到字符串为空。 如果字符串在过程结束时不为空,或者您找到不同类型的括号 - 则表示它不平衡。
示例:
([[{}]])
最后一个开头是{
,所以在找到之后查找}
- 从字符串中删除它并继续:
([[]])
等
如果字符串看起来像那样:
([[{]}])
所以在找到最后一个打开的({)
之后 - 你会看到在右括号之前有一个来自不同类型(])
的括号 - 所以它不平衡。
最糟糕的案例复杂性:O(n^2)
答案 1 :(得分:1)
我认为,出于教学目的,最好显示一个他们可能真正想出的简单算法?如果是这样,那么我认为一个非常直观的算法是删除()
的出现,直到没有更多要删除:
boolean isBalancedParens(String s) {
while (s.contains("()")) {
s = s.replace("()", "");
}
return s.isEmpty();
}
在对所调用的各种方法的性能的合理假设下,这将采用最坏情况 O ( n 2 )时间和 O ( n )额外空间。
答案 2 :(得分:0)
如果你的学生已经熟悉递归,这里有一个简单的想法:查看第一个括号,找到所有匹配的右括号,并为这些对中的每一个,用它们内部的子串和它们后面的子串递归。 ;例如:
input: "{(){[]}()}[]"
option 1: ^ ^
recurse with: "(){[]" and "()}[]"
"{(){[]}()}[]"
option 2: ^ ^
recurse with: "(){[]}()" and "[]"
如果输入为空字符串,则返回true。如果输入以右括号开头,或者输入不包含与第一个括号匹配的右括号,则返回false。
function balanced(input) {
var opening = "{([", closing = "})]";
if (input.length == 0)
return true;
var type = opening.indexOf(input.charAt(0));
if (type == -1)
return false;
for (var pos = 1; pos < input.length; pos++) { // forward search
if (closing.indexOf(input.charAt(pos)) == type) {
var inside = input.slice(1, pos);
var after = input.slice(pos + 1);
if (balanced(inside) && balanced(after))
return true;
}
}
return false;
}
document.write(balanced("{(({[][]}()[{}])({[[]]}()[{}]))}"));
&#13;
使用前向搜索更适合短平衡子串的连接;对于深度嵌套的字符串,使用向后搜索更好。但两者最坏的情况是O(n 2 )。