查找索引k,其中开括号和右括号的数量相同

时间:2017-01-19 21:56:24

标签: string algorithm performance

我遇到了这个问题但无法解决。
任务是在一组开/关括号中找到一个合适的索引,其中第一个k字符中的左括号数=剩余N-k个字符中右括号的数量。
防爆。

  

“(()))))(”k将是5,因为前5个字符“(()))”有2   打开括号,剩下的“))(”有2个右括号。   

另一个例子:

  

“()))()”k将是4.

k是独一无二的。解决方案应该是O(N)。

4 个答案:

答案 0 :(得分:4)

分别使用指向第一个和最后一个字符的两个索引。

虽然两个索引没有相互交叉,但按以下方式移动:

  • 如果左侧索引处的字符不是"(",则递增它;
  • 如果右侧索引处的字符不是")",则递减它;
  • 如果以上两者都不成立,则增加左侧索引并同时减少右侧索引

返回左侧索引。

这是JavaScript中的一个实现,它运行您给出的两个示例的算法:



function partition(s) {
    var i = 0;
    var j = s.length - 1;
    while (i <= j) {
        if (s[i] !== '(') {
            i++;
        } else if (s[j] !== ')') {
            j--;
        } else {
            i++;
            j--;
        }
    }
    return i;
}

console.log(partition("(()))))("));
console.log(partition("()))()"));
&#13;
&#13;
&#13;

随着索引在循环的每次迭代中彼此靠近,最多只有 n 次迭代。

答案 1 :(得分:3)

在预处理阶段,您可以计算字符串中的所有右括号(我们称之为c)。然后处理从左边开始的每个字符。我们用seenOpening表示已处理的左括号的数量,用unseenClosing表示尚未处理的右括号的数量。最初为seenOpening = 0unseenClosing = c。处理完每个字符后,根据括号的类型递增seenOpening或递减unseenClosing。每当seenOpening == unseenClosing终止并返回您已处理的最后一个字符的索引时。

答案 2 :(得分:1)

这是一个Java解决方案:

public int getIndexOnMatchingBracketCount(String str) { 
    int closingBracket = 0;
    int openingBracket = 0;

    for (int i = 0; i < s.length(); i++) {
        char c = s.charAt(i);
        if (c == ')') {
            closingBracket++;
        }
    }

    for (int i = 0; i < s.length(); i++) {
        if (openingBracket == closingBracket) {
            return i;
        }

        char c = s.charAt(i);
        if (c == ')') {
            closingBracket--;
        } else if (c == '(') {
            openingBracket++;
        }
    }

    return -1
}

答案 3 :(得分:0)

如果我们被允许使用O(n)空格,我们可以在O(n)中使用最少的逻辑非常轻松地完成此操作(如python中所示):

def find_index(str):

    n = len(str) 
    # O(n) space: no. of '(' in first k+1 and no. of ')' in last n-k characters
    opening_in_first_k, closing_in_last_n_k = [0]*n, [0]*n 

    for i in range(1, n): # O(n) time
        opening_in_first_k[i], closing_in_last_n_k[n-1-i] = opening_in_first_k[i-1] + (str[i] == '('), \
                                                            closing_in_last_n_k[n-i] + (str[n-1-i] == ')')
    for i in range(n): # O(n) time
        if opening_in_first_k[i] == closing_in_last_n_k[i+1]:
            return i

    return -1

print find_index("(()))))(")
# 5
print find_index("()))())")
# 4