Decode String

MediumRecursion · Stack🧩 Recursion & Divide and ConquerLeetCode #394 ↗Updated

Problem

A string is compressed with the rule k[body], meaning body written out k times; groups may be nested and mixed with plain letters. Given a valid encoded string s, return the fully expanded string.
Input3[a]2[bc]Outputaaabcbc
Input3[a2[c]]Outputaccaccacc
Input2[abc]3[cd]efOutputabcabccdcdcdef

1 ≤ |s| ≤ 30  ·  lowercase letters, digits, [ ]  ·  1 ≤ k ≤ 300  ·  output length ≤ 105  ·  input always valid

Try it yourself

Java
class Solution {
    public String decodeString(String s) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
Every [ opens a new “context” that must be finished before the outer one can continue. Save the outer text and its k on [, and on ] glue k copies of the inner text back onto it — recursion or a stack. (Below: L = output length, d = nesting depth.)
PatternRecursion & Divide and Conquer

Instinct If the answer for n items can be built from the same problem on halves (or smaller pieces) plus a cheap combine step - split, recurse, merge.

Memory hack Split it, trust it, stitch it - nail the base case, take the leap of faith on smaller calls, then glue their answers together.

Open the Recursion & Divide and Conquer guide →

Approaches

Brute ForceExpand Innermost Group Repeatedly

Time O(p·(n+L))Space O(n+L)

The first ] and the last [ before it form an innermost group whose body is letters only. Replace k[body] with body × k and repeat until no brackets remain. Each of the p expansions rebuilds the whole string.

Java
public String decodeString(String s) {
    int close;
    while ((close = s.indexOf(']')) != -1) {
        int open = s.lastIndexOf('[', close); // innermost pair
        int start = open;
        while (start > 0 && Character.isDigit(s.charAt(start - 1))) start--;
        int k = Integer.parseInt(s.substring(start, open));
        String body = s.substring(open + 1, close).repeat(k);
        s = s.substring(0, start) + body + s.substring(close + 1);
    }
    return s;
}

Simple string surgery, but re-copies the entire string once per bracket pair.

At a glance

LevelApproachTimeSpace
Brute ForceExpand Innermost Group RepeatedlyO(p·(n+L))O(n+L)
BetterRecursive DescentO(n + d·L)O(n+L)
OptimalTwo Stacks (Iterative)O(n + d·L)O(n+L)
Common pitfalls
  • Reading only one digit of k — breaks on 10[a] or 300[x].
  • Forgetting to reset k / cur after [.
  • Pushing cur.toString() and rebuilding the prefix on every ] — quadratic copying.
Interview tips
  • Say it is a grammar: str := (letter | k[str])* — recursion falls out of it.
  • Mention complexity depends on output length, not just |s|.
  • Trace 3[a2[c]] aloud, showing what each stack holds.
Pattern
Nested brackets → recursion / stack of contexts → parse, evaluate or expand nested structures.
My notes saved in this browser