
Problem Statement
Given a string s
which consists solely of the characters '(' and ')', the task is to determine the length of the longest substring where the parentheses are correctly matched and well-formed. This means that every opening parenthesis '(' has a corresponding closing parenthesis ')' and they are correctly nested according to the rules of typical parentheses sequences.
Examples
Example 1
Input:
s = "(()"
Output:
2
Explanation:
The longest valid parentheses substring is "()".
Example 2
Input:
s = ")()())"
Output:
4
Explanation:
The longest valid parentheses substring is "()()".
Example 3
Input:
s = ""
Output:
0
Constraints
0 <= s.length <= 3 * 104
s[i]
is'('
, or')'
.
Approach and Intuition
The challenge is to efficiently find the longest well-formed substring of parentheses. The solution needs to account for various cases of mismatch and nested parentheses. Here's how we can understand and approach this problem:
Brute Force Checking:
- One approach would be to generate all possible substrings of the given string and check if they are valid. However, this is impractical due to time complexity, especially considering the upper length constraint (up to 30,000).
Using Stack:
- A stack can effectively track unmatched opening parentheses.
- Traverse the string, pushing the index of each '(' onto the stack.
- For every ')', pop from the stack (matches the most recent '('), and calculate the length of the current valid string using the current index and the index at the top of the stack. This tells the width of the valid substring.
- If the stack becomes empty, push the current index on the stack. This helps record the place where the last valid substring ended.
Dynamic Programming:
- Maintain a DP array where
dp[i]
represents the length of the longest valid substring ending at indexi
. - If
s[i]
is '(', setdp[i] = 0
, as no valid substring can end with '('. - If
s[i]
is ')', determine if there is a '(' that matches this ')'. This is done by looking at the character before the beginning of the substring ending atdp[i-1]
. If this character is '(', then the substring is valid and can be extended.
- Maintain a DP array where
Without extra space:
- Traverse the string twice: once from left to right and once from right to left.
- Keep track of the counts of '(' and ')' during each traversal.
- In the left-to-right traversal, reset counters when ')' exceeds '(' since valid substrings must start afresh. Similarly, reset when '(' exceeds ')' in the right-to-left traversal.
By considering these approaches, particularly the use of a stack for linear time complexity, the solution becomes both efficient and straightforward to understand.
Solutions
- C++
- Java
- C
- JavaScript
- Python
class Solution {
public:
int findMaxLen(string str) {
int open = 0, close = 0, maxLen = 0;
for (int index = 0; index < str.length(); index++) {
if (str[index] == '(') {
open++;
} else {
close++;
}
if (open == close) {
maxLen = max(maxLen, 2 * close);
} else if (close > open) {
open = close = 0;
}
}
open = close = 0;
for (int index = str.length() - 1; index >= 0; index--) {
if (str[index] == '(') {
open++;
} else {
close++;
}
if (open == close) {
maxLen = max(maxLen, 2 * open);
} else if (open > close) {
open = close = 0;
}
}
return maxLen;
}
};
The provided C++ solution focuses on finding the longest length of a well-formed parentheses substring in a given string. The problem is approached using two scans of the input string: one left-to-right and the other right-to-left. This ensures that all possible valid substrings are considered, regardless of starting and ending positions.
- Begin by initializing two counters,
open
andclose
, to track the number of opening '(' and closing ')' parentheses respectively, and a variablemaxLen
to store the maximum length of valid parentheses found. - The first loop traverses the string from left to right:
- Increment the
open
counter when encountering '(' and theclose
counter when encountering ')'. - Check if
open
equalsclose
, indicating a potentially valid substring. If true, updatemaxLen
to the maximum of its current value or twice the value ofclose
. - Reset counters to zero if
close
exceedsopen
, as the substring can no longer be valid moving forward.
- Increment the
- Reset the counters and run a similar loop from right to left. This time focusing on handling cases where excess opening brackets might have invalidated potential substrings during the first pass:
- Increase
open
for '(' andclose
for ')'. - Update
maxLen
whenopen
equalsclose
. - Reset counters if
open
exceedsclose
.
- Increase
By processing the string in both directions, the solution efficiently identifies the maximum length of nested and sequential valid parentheses ensuring corner cases and overlapping substrings are addressed, resulting in the longest valid parentheses string being correctly determined.
public class Solution {
public int findMaxLen(String str) {
int open = 0, close = 0, maxlen = 0;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) == '(') {
open++;
} else {
close++;
}
if (open == close) {
maxlen = Math.max(maxlen, 2 * close);
} else if (close > open) {
open = close = 0;
}
}
open = close = 0;
for (int i = str.length() - 1; i >= 0; i--) {
if (str.charAt(i) == ')') {
close++;
} else {
open++;
}
if (open == close) {
maxlen = Math.max(maxlen, 2 * open);
} else if (open > close) {
open = close = 0;
}
}
return maxlen;
}
}
The given Java solution efficiently calculates the length of the longest valid parentheses substring. The approach utilizes a simple first pass through the string to record counts of open and close parentheses and a second pass to confirm or correct the maximal length found in the first pass.
- Count and match parentheses opening and closing during a forward traversal. When the counts are equal, potentially update the maximum length found so far. Reset counts when the number of close parentheses exceeds the open parentheses to ensure subsequences are valid.
- Repeat the logic in the reverse order (from the end of the string back to the start) to cover cases where an earlier close parenthesis may limit finding a longer valid substring during the forward pass.
- Make use of two iteration variables
open
andclose
both initialized at 0 for these counts. Update the maximum length usingMath.max(maxlen, 2 * [appropriate count])
during both forward and backward traverses. - The function returns the maximum length of valid parentheses found in the string, ensuring efficiency via two linear time complexity passes.
This method ensures accuracy by covering combinations of valid parentheses substrings from both directions and adjusts the sequence discontinuation based on imbalanced close or open parenthesis occurrences, making the solution robust and suitable for various input scenarios.
int maximum(int x, int y) { return (x > y ? x : y); }
int maxValidParenthesesLength(char* str) {
int open = 0, close = 0, maxLength = 0;
for (int index = 0; index < strlen(str); index++) {
if (str[index] == '(') {
open++;
} else {
close++;
}
if (open == close) {
maxLength = maximum(maxLength, 2 * close);
} else if (close > open) {
open = close = 0;
}
}
open = close = 0;
for (int index = strlen(str) - 1; index >= 0; index--) {
if (str[index] == '(') {
open++;
} else {
close++;
}
if (open == close) {
maxLength = maximum(maxLength, 2 * open);
} else if (open > close) {
open = close = 0;
}
}
return maxLength;
}
The provided C program defines a solution to find the length of the longest valid (properly closed and nested) parentheses substring. Follow these detailed insights into how the program accomplishes this:
Function Definitions & Purpose:
maximum(int x, int y)
: Helper function that returns the maximum of two integers.maxValidParenthesesLength(char* str)
: Main function which calculates the maximum length of valid parentheses.
Algorithm Breakdown: The solution uses two single-pass scans of the input string
str
:First Pass (Left to Right):
- Initializes two counters,
open
for '(' andclose
for ')'. - Iterates through the string from left to right.
- Increments
open
when '(' is encountered andclose
for ')'. - When
open
equalsclose
, it updates themaxLength
if the current valid substring is longer than previously recorded valid substrings. - If
close
exceedsopen
, it resets both counters to zero since the sequence is not valid starting from the previous '('.
- Initializes two counters,
Second Pass (Right to Left):
- Resets the
open
andclose
counters. - This pass ensures the validation of sequences that might start as invalid from the beginning of the string but become valid later.
- Proceeds similarly to the first pass but starts from the end of the string, counting and comparing as it moves towards the beginning.
- Resets the
Result Calculation:
- After both passes,
maxLength
holds the length of the longest valid parentheses substring found in the input string.
- After both passes,
This approach efficiently checks for valid sequences by considering every possible substring in two linear scans, guaranteeing the detection of the longest valid sequence of parentheses by balancing the counts in forward and reverse directions.
var maxValidParenthesesLength = function (str) {
let open = 0,
close = 0,
maxLen = 0;
for (let index = 0; index < str.length; index++) {
if (str[index] === "(") {
open++;
} else {
close++;
}
if (open === close) {
maxLen = Math.max(maxLen, 2 * close);
} else if (close > open) {
open = close = 0;
}
}
open = close = 0;
for (let index = str.length - 1; index >= 0; index--) {
if (str[index] === "(") {
open++;
} else {
close++;
}
if (open === close) {
maxLen = Math.max(maxLen, 2 * open);
} else if (open > close) {
open = close = 0;
}
}
return maxLen;
};
The JavaScript function maxValidParenthesesLength
calculates the length of the longest valid (properly closed and nested) parentheses substring within a given string str
. Implement a two-pass strategy ensuring a thorough scan from both left-to-right and right-to-left to account for all potential valid substrings.
- The variables
open
andclose
track the count of '(' and ')' respectively. maxLen
holds the maximum length of valid parentheses found during the scans.
First, traverse the string from left to right:
- Increment
open
each time a '(' is encountered andclose
for each ')'. - If
open
equalsclose
, calculate the length of current valid substring as2 * close
and updatemaxLen
if it's the longest found. - Reset
open
andclose
to zero ifclose
exceedsopen
which indicates an unmatched ')' disrupting a valid substring.
After completing the initial pass, initialize open
and close
to 0 again for a reverse scan from right to left:
- Perform similar updates to
open
andclose
but incrementopen
for '(' andclose
for ')'. - Check conditions similar to the forward pass for valid substrings and update
maxLen
if necessary. - Reset counts when
open
exceedsclose
.
Finally, return maxLen
representing the length of the longest valid parentheses substring determined after both passes. This ensures the function handles all variations and combinations by considering disruptions caused by unmatched parentheses from either end of the string.
class Solution:
def findLongestValid(self, sequence: str) -> int:
open_bracket, close_bracket, max_length = 0, 0, 0
for char in sequence:
if char == "(":
open_bracket += 1
else:
close_bracket += 1
if open_bracket == close_bracket:
max_length = max(max_length, 2 * close_bracket)
elif close_bracket > open_bracket:
open_bracket = close_bracket = 0
open_bracket = close_bracket = 0
for index in range(len(sequence) - 1, -1, -1):
if sequence[index] == "(":
open_bracket += 1
else:
close_bracket += 1
if open_bracket == close_bracket:
max_length = max(max_length, 2 * open_bracket)
elif open_bracket > close_bracket:
open_bracket = close_bracket = 0
return max_length
The Python code implements a solution to find the length of the longest valid parentheses substring within a given string. The approach involves two scans of the string:
The first scan moves from left to right:
- Initialize counters for open and close brackets (
open_bracket
,close_bracket
) and a variable to store the maximum length of valid parentheses (max_length
). - Increment
open_bracket
for every '(' found, andclose_bracket
for every ')'. - Whenever
open_bracket
equalsclose_bracket
, calculate potential max length as2 * close_bracket
and updatemax_length
if this is greater. - If
close_bracket
exceedsopen_bracket
at any point, reset both counters to zero since it's impossible to have a valid substring starting before this point.
- Initialize counters for open and close brackets (
The second scan moves from right to left:
- Reinitialize the
open_bracket
andclose_bracket
counters to zero. - This time, increment
open_bracket
for every '(' encountered andclose_bracket
for every ')'. - Match occurs when
open_bracket
equalsclose_bracket
, whereby the potential valid substring's length is computed as2 * open_bracket
. - Adjust the maximum length if this new calculated length exceeds the previously recorded
max_length
. - Reset counters to zero if
open_bracket
exceedsclose_bracket
, indicating invalid starting points for a substring.
- Reinitialize the
The function finally returns max_length
as the length of the longest valid parentheses substring found during the scans. This dual-scan technique efficiently checks valid substrings by considering balances from both ends of the sequence, ensuring all potential valid sequences are accounted for.
No comments yet.