带有平衡括号的子字符串

时间:2016-03-22 15:44:40

标签: string algorithm parentheses

以下问题在接受采访时被问到我的朋友:给出一个仅由'('和')'组成的字符串。查找带有平衡括号的子串的总数注意:输入字符串已经平衡。

我能想到这个问题的唯一解决方案是蛮力,需要n ^ 3次。是否有更快的解决方案。如果有,那么我也想知道这种方法的构建。

3 个答案:

答案 0 :(得分:3)

假设最终结果将是整数R.你应该在字符串上从左向右扫描然后,你应该保持一个堆栈Z,并在你从左向右扫描时更新它。

你最初应该把0推到Z.当你遇到一个'('在索引i,你应该把0推到S.当你遇到一个')'在索引i处,你应该将R增加(T *(T + 1)/ 2),T是Z的顶部元素。然后你应该弹出T,并将新的顶部元素增加1

一旦扫描完成,你应该再将R增加一倍(T *(T + 1)/ 2),因为我们最初放置的Z中仍有一个元素T.

使用堆栈Z的扫描应采用线性时间。下面是一个效率不高的Python实现,希望很容易理解。

def solve(s):
    R = 0
    Z = [0]
    for i in range(0, len(s)):
        if s[i] == '(':
            Z.append(0)
        else:
            R += Z[-1] * (Z[-1] + 1) / 2
            Z = Z[:-1]
            Z[-1] += 1
    R += Z[-1] * (Z[-1] + 1) / 2
    return R

递增R背后的想法如下。基本上你保留连续相同级别平衡字符串的数量,直到即将离开该级别。然后,当您即将进入更高级别时(即,当我们知道时,我们不会成为任何其他相同级别和连续的子字符串,我们会更新解决方案。

如果您考虑间隔有点不同,可以理解T *(T + 1)/ 2的值。让我们列举从1到T的那些连续的同级平衡子串。现在,使用这些子串选择平衡子串基本上是为我们更大的子串选择起点和终点。如果我们选择子串#1作为我们的起点,我们可以选择T个其他子串作为终点。对于#2,有(T-1),依此类推。基本上我们可以选择T *(T + 1)/ 2个不同的区间作为有效的balanged子字符串,这就是我们将R增加该值的原因。

我们应用于R的最终增量操作只是不省略最外层。

答案 1 :(得分:0)

我做了一个简单的算法来解决你的问题。请注意,它不会查找嵌套的平衡括号。

function TestAlgorithm(testString, resultCounter)
{
    if (!resultCounter)
        resultCounter = 0;

    var startIndex = testString.indexOf('(');

    if (startIndex === -1)
        return resultCounter;

    var endIndex = testString.indexOf(')', startIndex)

    if (endIndex === -1)
        return resultCounter;

    var newTestString = testString.substring(endIndex);

    return TestAlgorithm(newTestString, ++resultCounter);
}

答案 2 :(得分:0)

Every substring that's in scope begins with a '('. So my non-recursive approach would be:

total = 0
while string is not empty {
    count valid substrings beginning here -- add to total
    trim leading '(' and trailing ')' from string
    trim leading ')' and trailing '(' from string if present
}

count valid substrings beginning here can be done by stepping through char by char, incrementing a counter when you see '(' and decrementing when you see ')'. When a decrement results in zero, you're at the closing ')' of a balanced substring.