Program to find length of longest balanced subsequence in Python

When working with bracket sequences, finding the longest balanced subsequence is a common problem. A balanced bracket subsequence contains equal numbers of opening "(" and closing ")" brackets, where each closing bracket has a matching opening bracket before it.

So, if the input is like s = "())(()(" , then the output will be 4, as we can take the subsequence like "()()".

Algorithm Approach

The key insight is to traverse the string from right to left and use a greedy approach ?

  • Initialize result counter and closing bracket counter

  • Traverse string from right to left

  • Count closing brackets ")" as potential matches

  • When finding opening bracket "(", pair it with available closing bracket

  • Each successful pair contributes 2 to the result length

Implementation

def longest_balanced_subsequence(s):
    result = 0
    n = len(s)
    close_count = 0
    
    # Traverse from right to left
    for i in range(n - 1, -1, -1):
        if s[i] == ")":
            close_count += 1
        else:  # s[i] == "("
            if close_count > 0:
                close_count -= 1
                result += 2  # Found a balanced pair
    
    return result

# Test the function
s = "())(()("
print(f"Input: {s}")
print(f"Length of longest balanced subsequence: {longest_balanced_subsequence(s)}")
Input: ())(()( 
Length of longest balanced subsequence: 4

How It Works

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

def longest_balanced_subsequence_with_trace(s):
    result = 0
    close_count = 0
    n = len(s)
    
    print(f"Processing string: {s}")
    print("Traversing from right to left:")
    
    for i in range(n - 1, -1, -1):
        print(f"Position {i}: '{s[i]}'", end=" ")
        
        if s[i] == ")":
            close_count += 1
            print(f"? close_count = {close_count}")
        else:  # s[i] == "("
            if close_count > 0:
                close_count -= 1
                result += 2
                print(f"? Paired! close_count = {close_count}, result = {result}")
            else:
                print(f"? No closing bracket to pair with")
    
    return result

s = "())(()("
result = longest_balanced_subsequence_with_trace(s)
print(f"\nFinal result: {result}")
Processing string: ())(()( 
Traversing from right to left:
Position 6: '(' ? No closing bracket to pair with
Position 5: ')' ? close_count = 1
Position 4: '(' ? Paired! close_count = 0, result = 2
Position 3: ')' ? close_count = 1
Position 2: '(' ? Paired! close_count = 0, result = 4
Position 1: ')' ? close_count = 1
Position 0: '(' ? Paired! close_count = 0, result = 6

Final result: 6

Multiple Test Cases

def test_balanced_subsequence():
    test_cases = [
        "())(()(",     # Expected: 4
        "(((())))",    # Expected: 8  
        ")()())",      # Expected: 4
        "(((",         # Expected: 0
        ")))",         # Expected: 0
        "()()()",      # Expected: 6
        ""             # Expected: 0
    ]
    
    for s in test_cases:
        result = longest_balanced_subsequence(s)
        print(f"'{s}' ? {result}")

test_balanced_subsequence()
'())(()(' ? 4
'(((()))' ? 8
')()())' ? 4
'(((' ? 0
')))' ? 0
'()()()' ? 6
'' ? 0

Time and Space Complexity

  • Time Complexity: O(n) where n is the length of the string

  • Space Complexity: O(1) as we only use constant extra space

Conclusion

The right-to-left traversal approach efficiently finds the longest balanced subsequence by greedily pairing opening brackets with available closing brackets. This greedy strategy works because we want to maximize pairs, and processing from right ensures optimal matching.

Updated on: 2026-03-25T11:16:51+05:30

446 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements