Skip to content
AI360Xpert
Beta
Difficulty: MediumGreedy

Valid Parenthesis String

Problem in Plain English

You are given a string of opening brackets, closing brackets and stars, where each star may act as an opening bracket, a closing bracket, or nothing at all. Return whether some choice for every star makes the whole bracket sequence balanced.

Problem Statement

Given a string s containing only (, ) and *, determine whether s can be a valid parenthesis string, where each * may be treated as (, as ), or as an empty string.

A string is valid when every ( is closed by a later ) with correct nesting. Return true if some assignment of all stars achieves this, otherwise return false.

Constraints

  • The string length is between 1 and 100 inclusive.
  • Each character is (, ), or *.

Examples

Example 1

Input
s = "(*))"
Output
true

Assign the star to an opening bracket. The resulting (()) has prefix balances 1, 2, 1, 0, all nonnegative and ending at zero.

Example 2

Input
s = "()"
Output
true

The opening bracket at index 0 is closed at index 1. No wildcard choice is needed, and the final balance is zero.

Example 3

Input
s = "(*)"
Output
true

The star must be empty: assigning either bracket leaves a length-three sequence that cannot balance. Removing it leaves ().

Example 4

Input
s = "*"
Output
true

At the minimum input length, the only successful choice is an empty star, producing the valid empty sequence.

Example 5

Input
s = "*("
Output
false

The final opening bracket has no later character that can close it. An earlier star cannot serve as a closing bracket for a later opening bracket.

Example 6

Input
s = ")*"
Output
false

The first character closes a bracket before any opening is available. No assignment to a later star can repair that invalid prefix.

Intuition

A balanced sequence never closes more brackets than it has opened, and finishes with no unmatched opens. A star can change that running balance by +1, -1, or 0. For Example 1, "(*))", using the star as an opening bracket gives "(())". Instead of committing to one interpretation too soon, keep every feasible prefix balance, then ask whether zero remains feasible at the end.

Approaches

Memoized Recursion

Solution Details

Reveal Memoized Recursion: intuition, complexity, and code

Hints

Hint 1
A star triples the possibilities, but you only need to know how many open brackets could plausibly be pending.
Hint 2
Track the smallest and the largest open counts consistent with the prefix read so far.
Hint 3
A ) lowers both bounds and a * lowers the low bound while raising the high bound; clamp a negative low bound to zero and fail fast on a negative high bound.

Edge Cases

  • A single * and an all-star string are valid by making every star empty.
  • A single opening or 100 openings is invalid because no assignment can close them.
  • A leading closing bracket, including ")*", fails immediately; later stars cannot fix its prefix.
  • In "*(", the star appears too early to close the final opening. Ordering matters even when total counts could match.
  • For "(*)", the star must be empty, so checking only its bracket interpretations loses a valid solution.
  • A 100-character string of 50 openings followed by 50 closings exercises the maximum balance and deepest recursion.

Common Mistakes and Interview Tips

  • Choosing one permanent meaning for each star greedily can discard the only solution. Preserve the full feasible balance interval.
  • Clamping high to zero masks an empty feasible set and wrongly accepts strings such as ")*". Reject negative high first.
  • Leaving low negative keeps invalid prefix histories. For example, the single star must retain zero as its minimum feasible balance.
  • Returning high == 0 rejects "*" even though an empty assignment works. Test whether zero is feasible, using low == 0.
  • In memoization, checking cached values by truthiness loses cached false results; distinguish uncomputed entries explicitly.
  • Aliasing memo rows in Python or JavaScript corrupts position-specific results. Allocate an independent row for each position.
  • Interview tip: explain why reachable counts have no gaps; interval compression is correct here because a star includes the zero change as well as both bracket changes.

Key Takeaway

When one symbol fans out into many possibilities, tracking the whole interval of reachable balances replaces exponential branching with two running numbers.