Longest Valid Parentheses in Python

Finding the longest valid parentheses substring is a common problem that can be solved efficiently using a stack-based approach. Given a string containing only '(' and ')' characters, we need to find the length of the longest valid (well-formed) parentheses substring.

For example, in the string "))(())())", the longest valid parentheses substring is "(())())" with length 6.

Algorithm Approach

We use a stack to track indices of unmatched parentheses ?

  • Initialize a stack with −1 to handle edge cases

  • For each character, if it's '(', push its index onto the stack

  • If it's ')', check if it can form a valid pair with the top of stack

  • If valid pair found, pop from stack and update maximum length

  • If no valid pair, push current index (marks unmatched ')')

Implementation

def longest_valid_parentheses(s):
    stack = [-1]  # Initialize with -1 for base case
    max_length = 0
    
    for i in range(len(s)):
        if s[i] == "(":
            # Push index of opening parenthesis
            stack.append(i)
        else:  # s[i] == ")"
            # Check if we can form a valid pair
            if stack and stack[-1] != -1 and s[stack[-1]] == "(":
                stack.pop()  # Remove matched opening parenthesis
                max_length = max(max_length, i - stack[-1])
            else:
                # No matching opening parenthesis found
                stack.append(i)
    
    return max_length

# Test the function
test_string = "))(())())"
result = longest_valid_parentheses(test_string)
print(f"Input: {test_string}")
print(f"Longest valid parentheses length: {result}")
Input: ))(())())
Longest valid parentheses length: 6

How It Works

Let's trace through the example "))(())())" step by step ?

def trace_algorithm(s):
    stack = [-1]
    max_length = 0
    
    print(f"Processing string: {s}")
    print(f"Initial stack: {stack}")
    
    for i in range(len(s)):
        print(f"\nStep {i+1}: Processing '{s[i]}' at index {i}")
        
        if s[i] == "(":
            stack.append(i)
            print(f"  Pushed opening parenthesis index: {stack}")
        else:
            if stack and stack[-1] != -1 and s[stack[-1]] == "(":
                stack.pop()
                length = i - stack[-1]
                max_length = max(max_length, length)
                print(f"  Found valid pair! Stack after pop: {stack}")
                print(f"  Current length: {length}, Max length: {max_length}")
            else:
                stack.append(i)
                print(f"  No match found, pushed index: {stack}")
    
    return max_length

result = trace_algorithm("))(())())")
print(f"\nFinal result: {result}")
Processing string: ))(())())

Initial stack: [-1]

Step 1: Processing ')' at index 0
  No match found, pushed index: [-1, 0]

Step 2: Processing ')' at index 1
  No match found, pushed index: [-1, 0, 1]

Step 3: Processing '(' at index 2
  Pushed opening parenthesis index: [-1, 0, 1, 2]

Step 4: Processing '(' at index 3
  Pushed opening parenthesis index: [-1, 0, 1, 2, 3]

Step 5: Processing ')' at index 4
  Found valid pair! Stack after pop: [-1, 0, 1, 2]
  Current length: 2, Max length: 2

Step 6: Processing ')' at index 5
  Found valid pair! Stack after pop: [-1, 0, 1]
  Current length: 4, Max length: 4

Step 7: Processing '(' at index 6
  Pushed opening parenthesis index: [-1, 0, 1, 6]

Step 8: Processing ')' at index 7
  Found valid pair! Stack after pop: [-1, 0, 1]
  Current length: 6, Max length: 6

Step 9: Processing ')' at index 8
  No match found, pushed index: [-1, 0, 1, 8]

Final result: 6

Alternative Examples

# Test with different cases
test_cases = [
    "(()",      # Expected: 2
    ")()())",   # Expected: 4  
    "(()())",   # Expected: 6
    "()(()",    # Expected: 2
    ""          # Expected: 0
]

for test in test_cases:
    result = longest_valid_parentheses(test)
    print(f"'{test}' ? {result}")
'(()' ? 2
')()())' ? 4
'(()())' ? 6
')(((' ? 2
'' ? 0

Time and Space Complexity

Complexity Value Explanation
Time O(n) Single pass through the string
Space O(n) Stack can store up to n indices in worst case

Conclusion

The stack-based approach efficiently finds the longest valid parentheses by tracking unmatched indices. The algorithm runs in O(n) time and handles all edge cases including unmatched opening and closing parentheses.

---
Updated on: 2026-03-25T08:37:25+05:30

2K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements