Given a string s of '('
, ')'
and lowercase English characters.
Your task is to remove the minimum number of parentheses ( '('
or ')'
, in any positions ) so that the resulting parentheses string is valid and return any valid string.
Formally, a parentheses string is valid if and only if:
AB
(A
concatenated with B
), where A
and B
are valid strings, or(A)
, where A
is a valid string.
Example 1:
Input: s = "lee(t(c)o)de)" Output: "lee(t(c)o)de" Explanation: "lee(t(co)de)" , "lee(t(c)ode)" would also be accepted.
Example 2:
Input: s = "a)b(c)d" Output: "ab(c)d"
Example 3:
Input: s = "))((" Output: "" Explanation: An empty string is also valid.
Constraints:
1 <= s.length <= 105
s[i]
is either '('
, ')'
, or lowercase English letter.This problem asks us to find the minimum number of parentheses to remove from a given string to make it a valid parentheses string. A valid parentheses string is defined recursively:
The most efficient approach is a two-pass algorithm. We make one pass from left to right and another from right to left, removing invalid parentheses in each pass.
Algorithm:
Pass 1 (Left to Right):
open
to 0.(
, increment open
.)
:
open
is 0 (meaning we have more closing than opening parentheses), it's an extra closing parenthesis; remove it.open
.Pass 2 (Right to Left):
close
to 0.)
, increment close
.(
:
close
is 0 (meaning we have more opening than closing parentheses), it's an extra opening parenthesis; remove it.close
.Time and Space Complexity:
Code Implementations:
The code implementations below demonstrate the two-pass algorithm in various programming languages. Note that these implementations use different data structures to achieve the same goal. Some use stacks, while others build up the final string directly. The core logic remains the same.
(See the code examples in the original response)
Example Walkthrough:
Let's walk through s = "lee(t(c)o)de))"
:
Pass 1 (Left to Right):
l
, e
, e
: ignored(
: open
= 1t
: ignored(
: open
= 2c
: ignored)
: open
= 1o
: ignored)
: open
= 0d
: ignorede
: ignored)
: open
= 0 (extra closing parenthesis, removed))
: open
= 0 (extra closing parenthesis, removed)After Pass 1: "lee(t(c)o)de"
Pass 2 (Right to Left):
)
: close
= 1e
: ignoredd
: ignoredo
: ignored)
: close
= 2(
: close
= 1c
: ignored(
: close
= 0t
: ignored(
: close
= 0 (extra opening parenthesis, would be removed if present from the previous pass)e
: ignoredl
: ignorede
: ignoredThe result is "lee(t(c)o)de"
.
This two-pass approach provides a clear, efficient, and easy-to-understand solution to the problem. Other approaches, such as using a single pass with a stack, are possible, but they tend to be slightly more complex to implement and understand.