Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
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.
