📅  最后修改于: 2023-12-03 15:10:56.401000             🧑  作者: Mango
本文介绍如何用O(1)空间和O(N2)时间复杂度检查一个表达式中的平衡括号。
在编程中,我们经常需要使用括号来进行表达式的计算和逻辑判断。平衡括号指的是一个表达式中的所有左括号都能被一个右括号匹配。例如,下面的表达式是平衡的:
(1 + 2) * (3 - 4)
而这个表达式就不平衡:
(1 + 2 * (3 - 4)
要检查一个表达式中的平衡括号,我们需要从左到右扫描它的每一个字符。如果遇到左括号,就把它压入一个栈中。如果遇到右括号,就从栈中弹出一个左括号并判断它们是否匹配。如果不匹配,那么表达式就是不平衡的。
具体来说,我们定义两个指针 i
和 j
,分别表示当前扫描到的字符位置和栈中最后一个左括号的位置。我们从左到右依次扫描表达式中的每一个字符。当遇到左括号时,我们把它的位置记录到 j
中,并令 j=j+1
。当遇到右括号时,我们判断 j
是否为0,如果是,说明当前的右括号没有与任何一个左括号匹配,表达式不平衡;否则,我们把 j
的值减1,并判断左括号的位置,如果左括号的位置比当前右括号的位置更靠右,说明这两个括号没有配对,表达式不平衡。
下面是伪代码:
i = 0, j = 0
while i < N:
if s[i] == '(':
stack[j] = i
j += 1
else if s[i] == ')':
if j == 0:
return "Not Balanced"
j -= 1
if stack[j] > i:
return "Not Balanced"
i += 1
if j != 0:
return "Not Balanced"
return "Balanced"
上面的算法使用了一个栈来存储左括号的位置,需要额外的O(N)的空间。我们可以把栈存储在表达式中,用一个变量来代替。
具体来说,我们使用一个变量 cnt
来表示当前栈中左括号的数量。当遇到左括号时,我们把它的位置存储在表达式中当前位置的字符中,并把 cnt
的值加1。当遇到右括号时,我们先把当前位置的字符存储在栈顶的位置中,然后把 cnt
的值减1。如果 cnt
的值小于0,说明当前右括号没有匹配的左括号,表达式不平衡;否则,我们就继续扫描表达式。
这个算法的空间复杂度为O(1),但它需要修改表达式,增加了一些复杂度和风险。
下面是代码:
def check_balanced(expr):
cnt = 0
for i in range(len(expr)):
if expr[i] == '(':
cnt += 1
expr[i] = chr(cnt)
elif expr[i] == ')':
cnt -= 1
if cnt < 0:
return "Not Balanced"
expr[i] = expr[cnt]
return "Balanced" if cnt == 0 else "Not Balanced"
上面的算法的时间复杂度为O(N2),因为我们对于每一个右括号都需要遍历一遍栈来找到它匹配的左括号。我们可以通过把左括号的位置存储在一个数组中来优化这个过程。具体来说,我们用一个数组 match
来存储每一个左括号匹配的右括号的位置。当遇到左括号时,我们把它的位置存储在栈中,并更新 match
数组;当遇到右括号时,我们就可以直接使用 match
数组来查找它匹配的左括号的位置。这个算法的时间复杂度为O(N)。
下面是代码:
def check_balanced(expr):
n = len(expr)
cnt = 0
match = [-1] * n
for i in range(n):
if expr[i] == '(':
cnt += 1
match[cnt] = i
elif expr[i] == ')':
if cnt == 0:
return "Not Balanced"
j = match[cnt]
match[cnt] = -1
cnt -= 1
if j > i:
return "Not Balanced"
return "Balanced" if cnt == 0 else "Not Balanced"
本文介绍了如何用O(1)空间和O(N2)时间复杂度检查一个表达式中的平衡括号。我们还介绍了如何通过修改表达式和使用一个数组来优化算法的空间和时间复杂度。但这些算法对于含有大量括号的表达式可能会出现时间复杂度过高的情况,此时应当考虑使用更高级的算法或者数据结构来优化。