AlgoMaster Logo

Valid Parentheses

Last Updated: March 29, 2026

easy
3 min read

Understanding the Problem

We are given a string that contains only bracket characters, and we need to check whether every opening bracket has a matching closing bracket of the same type, and that they are nested correctly. The string "([)]" is invalid even though every bracket has a partner, because the nesting order is wrong. Meanwhile "([])" is valid because the inner brackets close before the outer ones.

The key observation is that the most recently opened bracket must be the first one to close. If you see (, then [, the [ must close before the ( can. This "last in, first out" behavior is exactly what a stack gives us. Every time we encounter an opening bracket, we push it onto the stack. Every time we see a closing bracket, we check if it matches the top of the stack. If the stack is empty at the end and every closing bracket matched its opener, the string is valid.

Key Constraints:

  • 1 <= s.length <= 10^4 → With at most 10,000 characters, even an O(n^2) approach would run in time, but O(n) is naturally achievable here.
  • s consists of parentheses only '()[]{}' → No need to handle other characters. We can safely assume every character is one of the six bracket types.

Approach 1: Repeated Replacement (Brute Force)

Intuition

The simplest idea is to observe that any valid string of brackets can be reduced to an empty string by repeatedly removing adjacent matching pairs. For example, "([])" contains "[]" as an adjacent pair. Remove it to get "()". That is also an adjacent pair. Remove it to get "". Empty string means valid.

So we can keep scanning the string and removing "()", "[]", and "{}" wherever they appear. If we eventually reduce the string to nothing, it is valid. If a pass through the string makes no removals and the string is not empty, it is invalid.

Algorithm

  1. Repeat the following until no more replacements are made:
    • Replace all occurrences of "()", "[]", and "{}" with empty string ""
  2. If the string is empty, return true
  3. Otherwise, return false

Example Walkthrough

1Initial string: "{[]}"
0
{
1
[
2
]
3
}
1/5

Code

This approach works correctly but rescans the entire string on every pass. What if we could process each character exactly once and immediately check whether it matches the most recently seen opening bracket?

Approach 2: Stack

Intuition

The repeated-replacement approach works but keeps re-scanning the string. The core insight is that bracket matching has a natural stack-based structure. When you read "([{", you are accumulating unmatched opening brackets. The most recent one, {, must be the first to close. This is exactly how a stack works: last in, first out.

Here is the idea: walk through the string one character at a time. If the character is an opening bracket ((, [, or {), push it onto the stack. If it is a closing bracket, check whether the top of the stack holds the matching opener. If it does, pop the stack and continue. If it does not, or if the stack is empty when we see a closing bracket, the string is invalid. After processing every character, the string is valid only if the stack is empty (no unmatched openers remain).

Algorithm

  1. Create an empty stack
  2. For each character in the string:
    • If the character is (, [, or {, push it onto the stack
    • If the character is ), ], or }:
      • If the stack is empty, return false (no matching opener)
      • Pop the top of the stack
      • If the popped bracket does not match the current closing bracket, return false
  3. After processing all characters, return true if the stack is empty, false otherwise

Example Walkthrough

1Start: scan string left to right, stack is empty
0
{
i
1
[
2
]
3
}
1/6

Code