Skip to content

1111. Maximum Nesting Depth of Two Valid Parentheses Strings

Description

A string is a valid parentheses stringΒ (denoted VPS) if and only if it consists of "(" and ")" characters only, and:

  • It is the empty string, or
  • It can be written asΒ ABΒ (AΒ concatenated withΒ B), whereΒ AΒ andΒ BΒ are VPS's, or
  • It can be written asΒ (A), whereΒ AΒ is a VPS.

We canΒ similarly define the nesting depth depth(S) of any VPS S as follows:

  • depth("") = 0
  • depth(A + B) = max(depth(A), depth(B)), where A and B are VPS's
  • depth("(" + A + ")") = 1 + depth(A), where A is a VPS.

For example,Β  "",Β "()()", andΒ "()(()())"Β are VPS's (with nesting depths 0, 1, and 2), and ")(" and "(()" are not VPS's.

Β 

Given a VPS seq, split it into two disjoint subsequences A and B, such thatΒ A and B are VPS's (andΒ A.length + B.length = seq.length).

Now choose any such A and B such thatΒ max(depth(A), depth(B)) is the minimum possible value.

Return an answer array (of length seq.length) that encodes such aΒ choice of A and B:Β  answer[i] = 0 if seq[i] is part of A, else answer[i] = 1.Β  Note that even though multiple answers may exist, you may return any of them.

Β 

Example 1:

Input: seq = "(()())"
Output: [0,1,1,1,1,0]

Example 2:

Input: seq = "()(())()"
Output: [0,0,0,1,1,0,1,1]

Β 

Constraints:

  • 1 <= seq.size <= 10000

Solutions

Solution 1: Greedy

We use a variable \(x\) to maintain the current balance of parentheses, which is the number of left parentheses minus the number of right parentheses.

We traverse the string \(seq\), updating the value of \(x\). If \(x\) is odd, we assign the current left parenthesis to \(A\), otherwise we assign it to \(B\).

The time complexity is \(O(n)\), where \(n\) is the length of the string \(seq\). Ignoring the space consumption of the answer, the space complexity is \(O(1)\).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class Solution:
    def maxDepthAfterSplit(self, seq: str) -> List[int]:
        ans = [0] * len(seq)
        x = 0
        for i, c in enumerate(seq):
            if c == "(":
                ans[i] = x & 1
                x += 1
            else:
                x -= 1
                ans[i] = x & 1
        return ans
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Solution {
    public int[] maxDepthAfterSplit(String seq) {
        int n = seq.length();
        int[] ans = new int[n];
        for (int i = 0, x = 0; i < n; ++i) {
            if (seq.charAt(i) == '(') {
                ans[i] = x++ & 1;
            } else {
                ans[i] = --x & 1;
            }
        }
        return ans;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class Solution {
public:
    vector<int> maxDepthAfterSplit(string seq) {
        int n = seq.size();
        vector<int> ans(n);
        for (int i = 0, x = 0; i < n; ++i) {
            if (seq[i] == '(') {
                ans[i] = x++ & 1;
            } else {
                ans[i] = --x & 1;
            }
        }
        return ans;
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
func maxDepthAfterSplit(seq string) []int {
    n := len(seq)
    ans := make([]int, n)
    for i, x := 0, 0; i < n; i++ {
        if seq[i] == '(' {
            ans[i] = x & 1
            x++
        } else {
            x--
            ans[i] = x & 1
        }
    }
    return ans
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
function maxDepthAfterSplit(seq: string): number[] {
    const n = seq.length;
    const ans: number[] = new Array(n);
    for (let i = 0, x = 0; i < n; ++i) {
        if (seq[i] === '(') {
            ans[i] = x++ & 1;
        } else {
            ans[i] = --x & 1;
        }
    }
    return ans;
}

Comments