InterviewPrepKit

Home / Coding / Greedy

Valid Parenthesis String

medium Original β†—
Solving tips
  • Key insight: with wildcards the count of unmatched '(' is a contiguous range [lo, hi], so track just the two endpoints instead of branching.
  • '(' raises both lo and hi; ')' lowers both; '*' lowers lo and raises hi.
  • Return False immediately if hi < 0 (too many ')'), and clamp lo at 0 since you can't owe negative opens; valid iff lo == 0 at the end.
  • Target O(n) time and O(1) space; check hi < 0 inside the loop, not just after it.

Problem

You are given a string s containing only the characters '(', ')', and '*'. Each '*' may be treated as a single '(', a single ')', or an empty string "". Decide whether there is some interpretation of the stars that makes s a valid parenthesis string.

A string is valid when every '(' has a matching ')' to its right, every ')' has a matching '(' to its left, and matches nest properly (equivalently: reading left to right, the running count of unmatched '(' never goes negative and ends at zero).

Return True if such an interpretation exists, otherwise False.

Examples

  • s = "()" β†’ True β€” already balanced.
  • s = "(*)" β†’ True β€” treat * as empty, leaving "()", which is valid.
  • s = "(*))" β†’ True β€” treat * as '(', giving "(())", which is valid.
  • s = ")(" β†’ False β€” the leading ')' has nothing to match and no star can fix it.

Constraints

  • 1 <= len(s) <= 100
  • s consists only of '(', ')', and '*'.
  • Small input, so even an O(n^2) DP passes β€” but an O(n) greedy is the elegant target.

Think about it first

Hint 1 If there were no stars, you'd just track a running count of open parens: +1 for '(', -1 for ')', never let it go negative, and require it to end at 0. Stars make the running count uncertain.
Hint 2 Because a star can act as '(', ')', or nothing, at each step the number of unmatched open parens is not a single value but a range. Track the minimum and maximum possible open count.
Hint 3 Keep lo = fewest possible open parens, hi = most. A '(' raises both; a ')' lowers both; a '*' lowers lo and raises hi. If hi ever drops below 0, too many ')' β€” invalid. Clamp lo at 0. Valid iff lo == 0 at the end.
Your workspace Not runnable by design β€” this is your interview scratchpad. Saved on this device.