Facebook Pixel

1614. Maximum Nesting Depth of the Parentheses

Problem Description

You are given a valid parentheses string s that may contain letters and parentheses characters ( and ). Your task is to find the nesting depth of the string, which is the maximum number of nested parentheses at any point in the string.

For example:

  • In the string "(())", the maximum nesting depth is 2 (when we reach the innermost parentheses)
  • In the string "(()(()))", the maximum nesting depth is 3
  • In the string "()()", the maximum nesting depth is 1

The solution works by tracking the current depth as we traverse the string. When we encounter an opening parenthesis (, we increase the current depth by 1 and update our maximum depth if needed. When we encounter a closing parenthesis ), we decrease the current depth by 1. Any other characters in the string are ignored.

The algorithm maintains:

  • Variable d to track the current nesting level
  • Variable ans to store the maximum depth seen so far

As we scan through each character:

  • If it's (: increment d and update ans = max(ans, d)
  • If it's ): decrement d
  • Otherwise: skip the character

Since the string is guaranteed to be valid (all parentheses are properly matched), the depth will always return to 0 by the end, and we return the maximum depth encountered during the traversal.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

Think of parentheses like entering and exiting nested rooms. Each opening parenthesis ( means we're entering a new room (going one level deeper), and each closing parenthesis ) means we're exiting a room (going back one level).

To find the maximum nesting depth, we need to track how deep we are at each moment and remember the deepest point we've reached.

Consider walking through the string "(()(()))":

  • Start at depth 0
  • See first (: enter room 1 (depth = 1)
  • See second (: enter room 2 (depth = 2)
  • See first ): exit back to room 1 (depth = 1)
  • See third (: enter another room 2 (depth = 2)
  • See fourth (: enter room 3 (depth = 3) - this is our deepest point!
  • See second ): exit to room 2 (depth = 2)
  • See third ): exit to room 1 (depth = 1)
  • See fourth ): exit to ground level (depth = 0)

The key insight is that we don't need to store the entire structure or use a stack. We just need a counter that goes up when we see ( and down when we see ). The maximum value this counter reaches during our traversal is the answer.

This works because the string is guaranteed to be valid - every opening parenthesis has a matching closing parenthesis, so our depth counter will never go negative and will return to 0 by the end.

Learn more about Stack patterns.

Solution Approach

We use a simple traversal approach with a counter to track the current nesting depth.

Variables needed:

  • d: Current depth counter, initialized to 0
  • ans: Maximum depth seen so far, initialized to 0

Algorithm:

  1. Iterate through each character c in the string s

  2. For each character:

    • If c == '(':
      • Increment the depth counter: d += 1
      • Update the maximum depth: ans = max(ans, d)
    • If c == ')':
      • Decrement the depth counter: d -= 1
    • For any other character (letters, etc.), do nothing
  3. Return ans as the final answer

Why this works:

The algorithm maintains the invariant that d always represents the current nesting level at any point during the traversal. Since we're guaranteed a valid parentheses string:

  • The depth d will never become negative
  • The depth d will return to 0 after processing all characters
  • The maximum value of d during traversal is exactly the nesting depth we're looking for

Time and Space Complexity:

  • Time: O(n) where n is the length of the string - we traverse the string once
  • Space: O(1) - we only use two integer variables regardless of input size

This greedy approach is optimal because we process each character exactly once and immediately update our answer, without needing to store any intermediate results or use additional data structures like a stack.

Ready to land your dream job?

Unlock your dream job with a 3-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through the string "(a(b)c)" to demonstrate the solution approach:

Initial state:

  • d = 0 (current depth)
  • ans = 0 (maximum depth seen)

Step-by-step traversal:

  1. Character '(': Opening parenthesis

    • Increment depth: d = 1
    • Update maximum: ans = max(0, 1) = 1
    • State: d = 1, ans = 1
  2. Character 'a': Letter (ignore)

    • No change to depth
    • State: d = 1, ans = 1
  3. Character '(': Opening parenthesis

    • Increment depth: d = 2
    • Update maximum: ans = max(1, 2) = 2
    • State: d = 2, ans = 2
  4. Character 'b': Letter (ignore)

    • No change to depth
    • State: d = 2, ans = 2
  5. Character ')': Closing parenthesis

    • Decrement depth: d = 1
    • State: d = 1, ans = 2
  6. Character 'c': Letter (ignore)

    • No change to depth
    • State: d = 1, ans = 2
  7. Character ')': Closing parenthesis

    • Decrement depth: d = 0
    • State: d = 0, ans = 2

Result: The maximum nesting depth is 2

The depth reached its peak of 2 when we were inside both sets of parentheses at character position 3. Notice how the depth counter correctly tracked our nesting level throughout, going up with each '(' and down with each ')', while ignoring the letters entirely.

Solution Implementation

1class Solution:
2    def maxDepth(self, s: str) -> int:
3        """
4        Calculate the maximum depth of nested parentheses in a string.
5      
6        Args:
7            s: Input string containing parentheses and other characters
8          
9        Returns:
10            Maximum nesting depth of valid parentheses
11        """
12        max_depth = 0  # Track the maximum depth encountered
13        current_depth = 0  # Track the current nesting level
14      
15        # Iterate through each character in the string
16        for char in s:
17            if char == '(':
18                # Opening parenthesis increases depth
19                current_depth += 1
20                # Update maximum depth if current is greater
21                max_depth = max(max_depth, current_depth)
22            elif char == ')':
23                # Closing parenthesis decreases depth
24                current_depth -= 1
25            # Other characters are ignored
26      
27        return max_depth
28
1class Solution {
2    /**
3     * Calculates the maximum depth of nested parentheses in a string.
4     * The depth is defined as the maximum number of nested parentheses at any point.
5     * 
6     * @param s The input string containing parentheses and other characters
7     * @return The maximum nesting depth of parentheses
8     */
9    public int maxDepth(String s) {
10        int maxDepth = 0;      // Tracks the maximum depth encountered
11        int currentDepth = 0;  // Tracks the current nesting level
12      
13        // Iterate through each character in the string
14        for (int i = 0; i < s.length(); i++) {
15            char currentChar = s.charAt(i);
16          
17            // Opening parenthesis increases the current depth
18            if (currentChar == '(') {
19                currentDepth++;
20                // Update maximum depth if current depth exceeds it
21                maxDepth = Math.max(maxDepth, currentDepth);
22            } 
23            // Closing parenthesis decreases the current depth
24            else if (currentChar == ')') {
25                currentDepth--;
26            }
27            // Other characters are ignored
28        }
29      
30        return maxDepth;
31    }
32}
33
1class Solution {
2public:
3    int maxDepth(string s) {
4        int maxNestingDepth = 0;  // Track the maximum nesting depth encountered
5        int currentDepth = 0;      // Track the current nesting depth while traversing
6      
7        // Iterate through each character in the string
8        for (char& ch : s) {
9            if (ch == '(') {
10                // Opening parenthesis increases the current depth
11                currentDepth++;
12                // Update maximum depth if current depth exceeds it
13                maxNestingDepth = max(maxNestingDepth, currentDepth);
14            } else if (ch == ')') {
15                // Closing parenthesis decreases the current depth
16                currentDepth--;
17            }
18            // Other characters are ignored (digits, operators, etc.)
19        }
20      
21        return maxNestingDepth;
22    }
23};
24
1/**
2 * Calculates the maximum depth of nested parentheses in a string
3 * @param s - Input string containing parentheses and other characters
4 * @returns The maximum nesting depth of valid parentheses
5 */
6function maxDepth(s: string): number {
7    // Track the maximum depth encountered
8    let maxDepthFound: number = 0;
9  
10    // Track the current depth while traversing
11    let currentDepth: number = 0;
12  
13    // Iterate through each character in the string
14    for (const character of s) {
15        if (character === '(') {
16            // Opening parenthesis increases current depth
17            currentDepth++;
18            // Update maximum depth if current depth is greater
19            maxDepthFound = Math.max(maxDepthFound, currentDepth);
20        } else if (character === ')') {
21            // Closing parenthesis decreases current depth
22            currentDepth--;
23        }
24        // Other characters are ignored
25    }
26  
27    return maxDepthFound;
28}
29

Time and Space Complexity

The time complexity is O(n), where n is the length of the string s. The algorithm iterates through each character in the string exactly once using a single for loop. Each operation inside the loop (comparison, increment/decrement, and max calculation) takes constant time O(1). Therefore, the total time complexity is O(n) * O(1) = O(n).

The space complexity is O(1). The algorithm only uses a fixed amount of extra space regardless of the input size. It maintains two integer variables: ans to track the maximum depth encountered and d to track the current depth. The loop variable c also uses constant space. Since the space usage doesn't grow with the input size, the space complexity is constant O(1).

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Updating Maximum Depth at the Wrong Time

A common mistake is updating the maximum depth when encountering a closing parenthesis ) or after modifying the depth counter, rather than immediately after incrementing for an opening parenthesis (.

Incorrect Implementation:

def maxDepth(self, s: str) -> int:
    max_depth = 0
    current_depth = 0
  
    for char in s:
        if char == '(':
            current_depth += 1
        elif char == ')':
            current_depth -= 1
            max_depth = max(max_depth, current_depth)  # Wrong place!
  
    return max_depth

This fails because when we encounter ), we've already decreased the depth, missing the peak depth that occurred just before.

Correct Approach: Update max_depth immediately after incrementing current_depth for opening parentheses.

2. Not Handling Empty Strings or Strings Without Parentheses

While the code handles these cases correctly (returning 0), developers might add unnecessary special case checks that complicate the code:

Overcomplicated:

def maxDepth(self, s: str) -> int:
    if not s or '(' not in s:  # Unnecessary checks
        return 0
    # ... rest of the code

The algorithm naturally handles these cases without special checks since the depth counters start at 0 and remain 0 if no parentheses are found.

3. Using a Stack When Not Necessary

Some developers might instinctively reach for a stack data structure since parentheses matching problems often use stacks:

Overly Complex:

def maxDepth(self, s: str) -> int:
    stack = []
    max_depth = 0
  
    for char in s:
        if char == '(':
            stack.append(char)
            max_depth = max(max_depth, len(stack))
        elif char == ')':
            stack.pop()
  
    return max_depth

While this works, it uses O(n) space unnecessarily when a simple counter suffices for tracking depth.

4. Forgetting to Skip Non-Parenthesis Characters

Attempting to process letters or other characters as parentheses:

Incorrect:

def maxDepth(self, s: str) -> int:
    max_depth = 0
    current_depth = 0
  
    for char in s:
        if char == '(':
            current_depth += 1
            max_depth = max(max_depth, current_depth)
        else:  # Wrong! This treats all non-'(' as ')'
            current_depth -= 1
  
    return max_depth

This incorrectly decrements depth for letters and other characters, potentially making depth negative.

Solution: Use explicit checks for both ( and ), ignoring all other characters.

Discover Your Strengths and Weaknesses: Take Our 3-Minute Quiz to Tailor Your Study Plan:

What's the output of running the following function using the following tree as input?

1def serialize(root):
2    res = []
3    def dfs(root):
4        if not root:
5            res.append('x')
6            return
7        res.append(root.val)
8        dfs(root.left)
9        dfs(root.right)
10    dfs(root)
11    return ' '.join(res)
12
1import java.util.StringJoiner;
2
3public static String serialize(Node root) {
4    StringJoiner res = new StringJoiner(" ");
5    serializeDFS(root, res);
6    return res.toString();
7}
8
9private static void serializeDFS(Node root, StringJoiner result) {
10    if (root == null) {
11        result.add("x");
12        return;
13    }
14    result.add(Integer.toString(root.val));
15    serializeDFS(root.left, result);
16    serializeDFS(root.right, result);
17}
18
1function serialize(root) {
2    let res = [];
3    serialize_dfs(root, res);
4    return res.join(" ");
5}
6
7function serialize_dfs(root, res) {
8    if (!root) {
9        res.push("x");
10        return;
11    }
12    res.push(root.val);
13    serialize_dfs(root.left, res);
14    serialize_dfs(root.right, res);
15}
16

Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More