Recursion
Programming
Algorithms
Balanced Parentheses
Computer Science

Basic Recursion, Check Balanced Parenthesis

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Checking whether parentheses are balanced is a classic algorithm exercise because it forces you to define correctness precisely. The recursive version is especially useful for learning how state moves through a problem one character at a time, even though an iterative stack is often the production-friendly solution.

For strings containing only ( and ), the rule is simple: the running balance must never drop below zero, and the final balance must be exactly zero. Recursion works well because those two conditions can be checked incrementally.

Write the Recursive Version Around a Running Count

The core idea is to walk through the string with two pieces of state:

  • the current index
  • the number of unmatched opening parentheses seen so far

Here is a direct recursive implementation in Python:

python
1def is_balanced(text):
2    def helper(index, open_count):
3        if open_count < 0:
4            return False
5
6        if index == len(text):
7            return open_count == 0
8
9        ch = text[index]
10
11        if ch == '(':
12            return helper(index + 1, open_count + 1)
13        if ch == ')':
14            return helper(index + 1, open_count - 1)
15
16        return helper(index + 1, open_count)
17
18    return helper(0, 0)
19
20
21print(is_balanced("(())()"))
22print(is_balanced("())("))

This solution is small, but it captures the entire problem. Every opening parenthesis increments the count. Every closing parenthesis decrements it. Any negative count means the string became invalid before it even ended.

Understand Why the Base Cases Are Correct

The recursive logic depends on two base cases.

First, if open_count ever becomes negative, the string is already invalid because a closing parenthesis appeared without a matching earlier opening parenthesis.

Second, when the recursion reaches the end of the string, the expression is balanced only if open_count == 0. A positive count at the end means there are unmatched opening parentheses left over.

Those rules explain why strings such as )( are invalid even though they contain the same number of opening and closing characters overall. The failure is in the order, not just the totals.

Compare It with a Stack-Based Solution

For this one-type problem, the counter is enough. Once multiple bracket types are introduced, a simple count no longer captures the ordering constraints correctly. At that point a stack is the better abstraction.

python
1def is_balanced_general(text):
2    pairs = {')': '(', ']': '[', '}': '{'}
3    stack = []
4
5    for ch in text:
6        if ch in "([{":
7            stack.append(ch)
8        elif ch in pairs:
9            if not stack or stack[-1] != pairs[ch]:
10                return False
11            stack.pop()
12
13    return not stack

This handles (), [], and {} because it remembers the exact opening symbols and their nesting order, which a single counter cannot do.

Know When Recursion Stops Being Practical

The recursive approach is excellent for teaching and interviews because it makes the logic explicit. In production, though, recursion depth matters. Very long inputs can hit recursion limits in languages such as Python.

That is why an iterative solution is often preferred for real parsers or large inputs. The algorithmic idea is the same, but iteration avoids the call-stack limit and is usually easier to optimize.

Still, recursion is valuable here because it trains the habit of expressing a problem in terms of state transitions and base cases. That habit generalizes well to tree traversal, backtracking, and divide-and-conquer problems.

Common Pitfalls

The biggest mistake is checking only whether the final count is zero. That misses cases like )(, where the total count balances but the order is invalid.

Another common mistake is using the one-counter solution for multiple bracket types. The moment bracket type and nesting order both matter, you need a stack or an equivalent structure.

It is also easy to forget what should happen with non-parenthesis characters. Some versions of the problem ignore them, while others reject them. The implementation should match the chosen rule explicitly.

Finally, recursive code can fail on very long inputs because of recursion depth, even when the logic is otherwise correct.

Summary

  • A balanced parenthesis string never goes negative and ends at zero.
  • A recursive helper can track the current index and open count cleanly.
  • Early failure on negative balance is essential for correctness.
  • Use a stack instead of a counter when multiple bracket types are involved.
  • Recursion is a good teaching tool here, even if iteration is often more practical.

Course illustration
Course illustration

All Rights Reserved.