String 带平衡圆括号的子字符串

String 带平衡圆括号的子字符串,string,algorithm,parentheses,String,Algorithm,Parentheses,在一次采访中,我向我的朋友提出了以下问题:给定一个仅由“(“and”)组成的字符串。查找带平衡圆括号的子字符串总数注意:输入字符串已平衡 我能想到的唯一解决这个问题的办法是暴力,它需要n^3倍的时间。有没有更快的解决方案。如果有,我也想知道该方法的构建。我做了一个简单的算法,可以解决您的问题。注意,它不寻找嵌套的平衡圆括号 function TestAlgorithm(testString, resultCounter) { if (!resultCounter) res

在一次采访中,我向我的朋友提出了以下问题:给定一个仅由“(“and”)组成的字符串。查找带平衡圆括号的子字符串总数注意:输入字符串已平衡


我能想到的唯一解决这个问题的办法是暴力,它需要n^3倍的时间。有没有更快的解决方案。如果有,我也想知道该方法的构建。

我做了一个简单的算法,可以解决您的问题。注意,它不寻找嵌套的平衡圆括号

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);
}

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

首先,你应该将0推到Z上。当你在索引i处遇到“(”时,你应该将0推到S上。当你在索引i处遇到a')时,你应该将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作为起点,那么就没有其他子串了我们可以选择s作为结束点。对于#2,有(T-1),以此类推。基本上,我们可以选择T*(T+1)/2个不同的间隔作为有效的平衡子串,这就是为什么我们将R增加该值


我们应用于R的最后一个增量操作只是为了不忽略最外层。

范围内的每个子字符串都以“(”开头。因此我的非递归方法是:

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从这里开始的有效子字符串
可以通过逐个字符进行计数,当看到“(”时递增,当看到“')”时递减。当递减结果为零时,即为结束“)'的平衡子字符串。

请发布您到目前为止的代码。现在没有做任何代码,我现在只能想到蛮力,即对于每个子字符串检查它是否有平衡的Parethes。检查将需要O(长度)使用堆栈的时间。我想先考虑algo,然后编写代码。是的,你可以做得更好。尝试递归思考(尽管你可以很容易地重构为迭代解决方案)。你现在知道如何检查字符串的平衡吗?如果是,那么你可以很容易地得到O(n^2)解决方案请看:您的方法的时间复杂度,先生???@suraj您所做的只是扫描字符串。如果您使用适当的堆栈(即不像我那样使用列表),那么您在循环的每个迭代中所做的一切都需要恒定的时间。因此,复杂度与字符串的长度成线性关系。