🧠
Two-Pass Counter Approach (Left-Right Scan)
💡 This approach uses two passes with counters to track the number of '(' and ')' seen, allowing us to find valid substrings without extra space.
Intuition
Scan from left to right counting '(' and ')'. When counts match, update max length. If ')' count exceeds '(', reset counters. Repeat scanning from right to left to catch valid substrings missed in first pass.
Algorithm
- Initialize left and right counters to zero.
- Scan string from left to right: increment left for '(' and right for ')'.
- When left equals right, update max length; if right exceeds left, reset counters.
- Reset counters and scan from right to left similarly, incrementing counters accordingly.
- Return the maximum length found.
💡 Two passes ensure all valid substrings are counted, including those with unmatched '(' at the start or end.
def longestValidParentheses(s: str) -> int:
left = right = max_len = 0
# Left to right scan
for ch in s:
if ch == '(': left += 1
else: right += 1
if left == right:
max_len = max(max_len, 2 * right)
elif right > left:
left = right = 0
left = right = 0
# Right to left scan
for ch in reversed(s):
if ch == ')': right += 1
else: left += 1
if left == right:
max_len = max(max_len, 2 * left)
elif left > right:
left = right = 0
return max_len
# Driver code
if __name__ == '__main__':
test_cases = ["(()", ")()())", "", "()()()", "((((", "))))"]
for tc in test_cases:
print(f"Input: {tc} -> Longest Valid Parentheses: {longestValidParentheses(tc)}")
Line Notes
left = right = max_len = 0Initialize counters and max length
for ch in s:Left to right scan over string
if ch == '(': left += 1Count '(' characters
elif right > left: left = right = 0Reset counters if ')' exceed '('
for ch in reversed(s):Right to left scan to catch missed valid substrings
if left == right: max_len = max(max_len, 2 * left)Update max length when balanced
public class Solution {
public static int longestValidParentheses(String s) {
int left = 0, right = 0, maxLen = 0;
// Left to right scan
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '(') left++;
else right++;
if (left == right) maxLen = Math.max(maxLen, 2 * right);
else if (right > left) left = right = 0;
}
left = right = 0;
// Right to left scan
for (int i = s.length() - 1; i >= 0; i--) {
if (s.charAt(i) == ')') right++;
else left++;
if (left == right) maxLen = Math.max(maxLen, 2 * left);
else if (left > right) left = right = 0;
}
return maxLen;
}
public static void main(String[] args) {
String[] testCases = {"(()", ")()())", "", "()()()", "((((", "))))"};
for (String tc : testCases) {
System.out.println("Input: " + tc + " -> Longest Valid Parentheses: " + longestValidParentheses(tc));
}
}
}
Line Notes
int left = 0, right = 0, maxLen = 0;Initialize counters and max length
for (int i = 0; i < s.length(); i++)Left to right scan
if (s.charAt(i) == '(') left++;Count '(' characters
else if (right > left) left = right = 0;Reset counters if ')' exceed '('
for (int i = s.length() - 1; i >= 0; i--)Right to left scan
if (left == right) maxLen = Math.max(maxLen, 2 * left);Update max length when balanced
#include <iostream>
#include <string>
using namespace std;
int longestValidParentheses(string s) {
int left = 0, right = 0, maxLen = 0;
// Left to right scan
for (char ch : s) {
if (ch == '(') left++;
else right++;
if (left == right) maxLen = max(maxLen, 2 * right);
else if (right > left) left = right = 0;
}
left = right = 0;
// Right to left scan
for (int i = (int)s.size() - 1; i >= 0; i--) {
if (s[i] == ')') right++;
else left++;
if (left == right) maxLen = max(maxLen, 2 * left);
else if (left > right) left = right = 0;
}
return maxLen;
}
int main() {
string testCases[] = {"(()", ")()())", "", "()()()", "((((", "))))"};
for (auto& tc : testCases) {
cout << "Input: " << tc << " -> Longest Valid Parentheses: " << longestValidParentheses(tc) << endl;
}
return 0;
}
Line Notes
int left = 0, right = 0, maxLen = 0;Initialize counters and max length
for (char ch : s)Left to right scan
if (ch == '(') left++;Count '(' characters
else if (right > left) left = right = 0;Reset counters if ')' exceed '('
for (int i = (int)s.size() - 1; i >= 0; i--)Right to left scan
if (left == right) maxLen = max(maxLen, 2 * left);Update max length when balanced
function longestValidParentheses(s) {
let left = 0, right = 0, maxLen = 0;
// Left to right scan
for (const ch of s) {
if (ch === '(') left++;
else right++;
if (left === right) maxLen = Math.max(maxLen, 2 * right);
else if (right > left) left = right = 0;
}
left = right = 0;
// Right to left scan
for (let i = s.length - 1; i >= 0; i--) {
if (s[i] === ')') right++;
else left++;
if (left === right) maxLen = Math.max(maxLen, 2 * left);
else if (left > right) left = right = 0;
}
return maxLen;
}
// Test cases
const testCases = ["(()", ")()())", "", "()()()", "((((", "))))"];
for (const tc of testCases) {
console.log(`Input: ${tc} -> Longest Valid Parentheses: ${longestValidParentheses(tc)}`);
}
Line Notes
let left = 0, right = 0, maxLen = 0;Initialize counters and max length
for (const ch of s)Left to right scan
if (ch === '(') left++;Count '(' characters
else if (right > left) left = right = 0;Reset counters if ')' exceed '('
for (let i = s.length - 1; i >= 0; i--)Right to left scan
if (left === right) maxLen = Math.max(maxLen, 2 * left);Update max length when balanced
Two passes over the string with constant extra space for counters.
💡 For n=10^5, this means about 200,000 operations, very efficient and minimal memory use.
Interview Verdict: Accepted
This approach is optimal in space and time, making it a great alternative to the stack method.