问题是:
给出一个仅包含字符'('和')'的字符串,找到最长的有效(格式正确)括号子字符串的长度
一些例子是:
输入:“(()”,输出:2
输入:“)()())”,输出4
我在下面找到了这个可行的Python解决方案:
def solution(s):
if not s or len(s) == 1:
return 0
stack = [-1]
a = 0
for i,c in enumerate(s):
if c == '(':
stack.append(i)
else:
stack.pop()
if stack:
a = max(a, i - stack[-1])
else:
stack.append(i)
return a
我无法理解此解决方案为何有效。我已经逐步处理了一些示例输入,但是我看不出它为什么起作用。
如果我理解正确,那么每次遇到左括号时,堆栈都会简单地添加索引。否则,将弹出堆栈,并采用当前索引和最后一个左括号之间的差值。
我的问题是,为什么先弹出堆栈然后再测量长度?为什么我们从第二个括号到最后一个括号进行测量?如果堆栈为空,我也无法理解为什么会有stack.append(i)
:我不明白这里的逻辑。
答案 0 :(得分:0)
堆栈包含不平衡字符的索引,始终按升序排列。堆栈的顶部(即stack
列表中的最后一个值)是当前不平衡的最右边字符(或-1
的特殊索引,指的是“开始”之前的位置)。字符串(如果当前没有任何不平衡字符)。
堆栈的底部是最右边的不平衡)
字符的索引,如果到目前为止还没有发现不平衡的-1
,则为)
。堆栈中的所有其他值将始终是迄今为止不平衡的(
字符的索引。随着我们继续遍历字符串,我们稍后可能会平衡它们。
当我们在输入字符串上的迭代中遇到一个新字符时,我们可能会采取三种可能的操作。
(
,我们知道它是不平衡的(目前,因为它是我们处理的最后一个字符),所以我们总是将其压入堆栈顶部。在其他两种情况下,新字符为)
。对于这两者,我们都希望从堆栈顶部弹出一个值,因为前一个值不再是最右边的不平衡字符。
如果在我们弹出值之后堆栈不为空,则弹出的索引表示不平衡的(
字符,而当前的)
刚刚使它平衡。
在这种情况下,我们当前的字符是平衡子字符串的一部分,因此我们检查它是否是迄今为止我们所见过的最长的子字符串。堆栈中的最后一个值是最右边的不平衡字符的索引,而我们的平衡子字符串就从其右边开始。因此,当前子字符串的长度为i - stack[-1]
,并且如果max
调用大于{{1},它将用新长度替换a
(以前看到的最长子字符串的长度)。 }}的旧值。
如果在我们弹出一个值后堆栈为空,那么我们弹出的值就是堆栈的底部。正如我在上面提到的,最低值是不平衡的a
字符(或)
代表字符串的开头)的索引。如果我们弹出它,则意味着我们当前的-1
不平衡!在这种情况下,我们用自己的索引替换弹出的值。这是堆栈的新底部,是最右边的新不平衡)
的索引。