PracticeNeetCode ↗LeetCode ↗
Given a string s made only of '(', ')', and '*' — where each '*' can stand in for '(', ')', or an empty string — return true if some interpretation of the '*'s makes s a valid parentheses string.
'*' is exponential — instead track a range [loMin, hiMax] of possible open-paren counts as you scan.'(' raises both bounds, ')' lowers both, and '*' lowers the low bound while raising the high bound — covering all three interpretations in one step.loMin can never go below 0 (clamp it back up); if hiMax ever drops below 0, no interpretation can recover and the answer is false immediately.loMin = 0, hiMax = 0.c: if '(', increment both bounds; if ')', decrement both; if '*', decrement loMin and increment hiMax.hiMax < 0 at any point, return False.loMin to 0 whenever it goes negative.True if loMin == 0, else False.Time: O(n) — Space: O(1)
def checkValidString(s: str) -> bool:
loMin, hiMax = 0, 0
for c in s:
if c == "(":
loMin += 1
hiMax += 1
elif c == ")":
loMin -= 1
hiMax -= 1
else:
loMin -= 1
hiMax += 1
if hiMax < 0:
return False
loMin = max(loMin, 0)
return loMin == 0How the solution above works, piece by piece.
*, track the range of possible open-bracket counts: loMin (fewest) to hiMax (most).( raises both; ) lowers both; * could be ), empty or (, so it lowers loMin and raises hiMax.) no matter what → False.loMin at 0.loMin == 0. O(n) time, O(1) space.Running it on s = "(*))":
( after that character. The range never goes fully negative, and 0 is inside it at the end, so the string can be valid (the * acts as ().