THE WHY BEHIND EVERY DSA PROBLEM
SHEET: STRIVER A2Z · REV 0.1
UNDERSTOOD: 0 / 79 DRAFTED
STEP 5 · STRINGS · DEPTH COUNTER · EASY

Remove Outermost Parentheses

WHAT IT SAYS

A valid parentheses string splits into primitive pieces; strip the outermost bracket pair from each piece and concatenate what is left.

WHAT IT'S REALLY ASKING

"A primitive ends the instant your debt returns to zero. So do not parse anything, do not find matching pairs, do not build pieces. Just carry a running balance and ask of each bracket: are you the one that opens the debt, or the one that clears it?"

THE INSIGHT LADDER — FROM BRUTE FORCE TO OPTIMAL

Find the primitives, slice them, strip them

O(n) time, O(n) space

Push indices of '(' on a stack and pop on ')'. When the stack empties you have closed a primitive, so slice that substring out, drop its first and last characters, and append the remainder to the answer.

WHERE THE WORK IS WASTED — Look at what the stack is actually used for. You push indices, but you never READ one — the only thing the code ever asks is whether the stack is empty. A stack whose contents are never inspected is an integer wearing a costume, and it is costing you O(n) memory to hold data you have no use for. Then the slicing copies every primitive into a fresh string purely to remove two characters from its ends.

!
KEY OBSERVATION — THE UNLOCKlink

A bracket is outermost exactly when the balance touches zero.

Define the balance as the number of '(' seen minus the number of ')' seen. Walk the string and watch it. A primitive, by definition, is a maximal balanced chunk — so a primitive BEGINS exactly at an '(' that arrives when the balance is 0 (nothing is open, the debt is clear, a new piece must be starting). And it ENDS exactly at the ')' that returns the balance to 0 (the debt is cleared again). Those two characters, and only those two, are the outermost pair of that primitive. Every other bracket in the string is, by construction, strictly inside some primitive: it arrived while the balance was already positive and it left the balance positive. Those are precisely the characters that survive. So each character's fate is decided by one integer — the balance at the moment you meet it. Not by what came before, not by what comes after, not by which bracket matches which. There is nothing to remember, so there is nothing to store.

One counter, one pass

O(n) time, O(1) extra space beyond the output

Carry depth, starting at 0. On '(': append it to the output only if depth is already greater than 0, then increment. On ')': decrement first, then append it only if depth is still greater than 0. That asymmetry — increment after, decrement before — is what makes both zero-crossings get dropped.

WHAT YOU TRADED — You throw away every scrap of structure: after this you cannot say which primitive a character came from, how deep it was, or where the pieces began. You also quietly assume the input is valid — a stray ')' drives the balance negative and the code cheerfully produces nonsense. And the reduction is fragile in one specific way: it works because there is only ONE kind of bracket. Add '[' and '{' and the count is no longer enough, because you would need to know WHAT is open, not just how much. That is exactly the line between this problem and Valid Parentheses.
WATCH THE IDEA RUN
(
0
(
1
)
2
(
3
)
4
)
5
(
6
)
7
balance 0
output -
memory used 1 integer
Balance starts at zero. Nothing is open, so the very next '(' has to be the start of a primitive.
step 1 / 10
THE PATTERN — SO YOU RECOGNIZE IT NEXT TIME

The Stack Is Just a Counter

YOU'LL SEE IT AGAIN WHEN

  • You are walking a nested or balanced structure but you only ever ask about DEPTH — never about the identity of what is currently open.
  • There is only one kind of bracket / symbol, so what is on the stack carries no information beyond how much of it there is.
  • Each element's fate is decided by a running scalar (a balance, a parity, a count) available in a single pass, and the naive solution builds substrings or a parse tree only to flatten it again.

SAME BLUEPRINT, DIFFERENT PROBLEM

Maximum Nesting Depth of the ParenthesesValid Parentheses (contrast: several bracket types force a real stack)Minimum Add to Make Parentheses ValidScore of Parentheses (contrast: the stack's contents do matter)
The bar isn't "solved it once." It's "could rebuild it from the observation."