The O(n) Club: All Possible Parentheses — Recursion Goes Wild

The O(n) Club: All Possible Parentheses — Recursion Goes Wild

⚡ TL;DR

Given an expression like “2*3-4*5”, your job is to group numbers using parentheses every conceivable way, then return all results. Think: giving a spreadsheet every possible bracket combo and asking, ‘Which sum breaks first?’ Naive recursion works but is slower than loading Eclipse with 50 plugins. Witness Java in the wild:

// Brute-force. Only for the brave (or desperate):
public List<Integer> diffWaysToCompute(String input) {
  List<Integer> out = new ArrayList<>();
  for (int i = 0; i < input.length(); i++) {
    char c = input.charAt(i);
    if (c == '+' || c == '-' || c == '*') {
      List<Integer> left = diffWaysToCompute(input.substring(0, i));
      List<Integer> right = diffWaysToCompute(input.substring(i+1));
      for (int l : left) for (int r : right)
        out.add(c == '+' ? l+r : c == '-' ? l-r : l*r);
    }
  }
  if (out.isEmpty()) out.add(Integer.parseInt(input));
  return out;
}

🧠 How Devs Usually Mess This Up

#1 – Doing everything left-to-right: This isn’t school math. Every operator screams: “Split me!” Process all of them. If you go left-to-right only, you get one answer. The interviewer gets a new favorite candidate—anyone but you.

#2 – Forgetting the base case: When the string is just digits (like “12”), return it as a single result, or Java’s going to treat your recursion like infinite monkeys on typewriters.

#3 – No memoization: Welcome to O(2^N) recursive doomsday. Enjoy your frying laptop. Cache, cache, cache!

🔍 What’s Actually Going On

Picture this problem as an office whiteboard, where each operator (+, -, *) is a possible way to split your equation. For every split, recursively solve left and right, mix the results every way you can—then repeat, forever. It’s like evaluating a circuit with every possible wiring, or running a “what if” on every spreadsheet scenario.
Memoization is your friend: store results for any repeated sub-expression. Otherwise, you’re just running in circles, like a mutex waiting for a rogue thread.

🛠️ PseudoCode

  • If input only has digits:
    if (input is just a number)
      return [number]

    And breathe. This is your recursion anchor.

  • For each character in input:
    for (char c : input)
      if c is +, - or *
        left = compute(left half)
        right = compute(right half)

    Every operator is a party invitation for parentheses.

  • Combine all combos:
    for (l : left)
      for (r : right)
        result.add(apply(l, r, operator))

    Double loops, double the fun. (Not really.)

  • Memoize:
    memo[input] = result

    Otherwise, say goodbye to runtime as you know it.

💻 The Code

import java.util.*;
public class Solution {
    private Map<String, List<Integer>> memo = new HashMap<>();
    public List<Integer> diffWaysToCompute(String input) {
        if (memo.containsKey(input)) return memo.get(input);
        List<Integer> out = new ArrayList<>();
        for (int i = 0; i < input.length(); i++) {
            char c = input.charAt(i);
            if (c == '+' || c == '-' || c == '*') {
                List<Integer> left = diffWaysToCompute(input.substring(0, i));
                List<Integer> right = diffWaysToCompute(input.substring(i+1));
                for (int l : left)
                    for (int r : right)
                        out.add(c == '+' ? l+r : c == '-' ? l-r : l*r);
            }
        }
        if (out.isEmpty()) out.add(Integer.parseInt(input));
        memo.put(input, out);
        return out;
    }
}

⚠️ Pitfalls, Traps & Runtime Smacks

  • Skipping the base case: Infinite recursion: not as fun as it sounds.
  • Ignoring multi-digit numbers: ‘12’ isn’t ‘1’ then ‘2’. Don’t rewrite history—parse responsibly.
  • No memo? Bad times: Without caching, the only thing you’ll produce is regret.
  • Duplicates happen: Different splits may yield the same output—no need to dedupe, that’s not the goal here.
  • Complexity check: Memoized: O(N * 2^N) time-ish. Not memoized: O(wait until next interview).

🧠 Interviewer Brain-Tattoo

“Every operator’s a branching path in the recursion amusement park—visit them all, but don’t forget to stamp your ticket (memoization) before reriding!”

Previous Article

The O(n) Club: Constructing BST from Preorder — Recursion, Not Regret

Next Article

The O(n) Club: Add Two Numbers II: Making Linked Lists Add Like 80s Calculators