#394 Decode String
frequently reported atBloombergByteDance / TikTokGoogleMetaAmazonMicrosoft
the problem
In plain words
Decode a string encoded as k[encoded], meaning the inside is repeated k times. Encodings can nest, e.g. "3[a2[c]]". Digits only appear as repeat counts.
in s = "3[a]2[bc]"
out "aaabcbc"
in s = "3[a2[c]]"
out "accaccacc"
in s = "2[abc]3[cd]ef"
out "abcabccdcdcdef"
- 1 ≤ s.length ≤ 30
- 1 ≤ k ≤ 300
- s is a valid encoding; the output length ≤ 10⁵
your turn
Try it before you peek
Read the examples, say the brute force out loud, then write code: here or on LeetCode ↗. Stuck for 20 minutes? Open one hint at a time.
Solve it in the browser
LeetCode-style: complete the class. Compiled by the real javac (Java 17) and judged right here — nothing is sent anywhere.
Solutions are hidden so you can try first. Even 20 minutes of real effort makes the answer stick far better than reading it.
Marking the problem solved, or opening every hint, also shows it.
the aha
Key insight
patternStack for matching & nestingString parsing
On '[' you start a new inner string, but you must remember the outer text and the count. On ']' you finish the inner string, repeat it, and glue it back onto the outer text — save on open, restore on close: a stack.
solutions
From brute force to optimal
The first ']' closes an innermost group. Expand it in the string and start over.
- Find the first ']' and the last '[' before it.
- Read the number before '['.
- Replace k[inner] with inner repeated k times.
- Repeat until no '[' remains.
b bracket groups, and each rewrite copies the whole string, up to the output length L.
The rewritten string.
class Solution { public String decodeString(String s) { while (s.indexOf('[') >= 0) { int close = s.indexOf(']'); // first ']' closes the innermost group int open = s.lastIndexOf('[', close); // its matching '[' int start = open; while (start > 0 && Character.isDigit(s.charAt(start - 1))) start--; int k = Integer.parseInt(s.substring(start, open)); String inner = s.substring(open + 1, close); s = s.substring(0, start) + inner.repeat(k) + s.substring(close + 1); } return s; }}cur builds the current level. '[' pushes (k, cur) and starts fresh; ']' pops them and appends the repeated inner text.
- Digit → k = k·10 + digit (counts can be multi-digit).
- '[' → push k and cur; cur = new builder; k = 0.
- ']' → cur = outer.pop() + cur repeated counts.pop() times.
- Letter → append to cur.
Each output character is copied once per enclosing bracket level (d = max nesting depth).
The builders on the stack plus the result.
class Solution { public String decodeString(String s) { Deque<Integer> counts = new ArrayDeque<>(); Deque<StringBuilder> outer = new ArrayDeque<>(); // text built before each '[' StringBuilder cur = new StringBuilder(); int k = 0; for (char c : s.toCharArray()) { if (Character.isDigit(c)) { k = k * 10 + (c - '0'); // numbers can have several digits ("12[a]") } else if (c == '[') { counts.push(k); // save the context, start fresh inside outer.push(cur); cur = new StringBuilder(); k = 0; } else if (c == ']') { String inner = cur.toString(); cur = outer.pop().append(inner.repeat(counts.pop())); // glue back onto the outside } else { cur.append(c); } } return cur.toString(); }}Dry run
decode() reads until ']' and returns its text; '[' calls decode() for the inner part.
- Shared index i.
- Digit → build k. '[' → append decode() repeated k times. ']' → return. Letter → append.
Same copying as the two-stack version.
Builders along the recursion path (depth d) plus the result.
class Solution { private int i; // shared read position public String decodeString(String s) { i = 0; return decode(s); } private String decode(String s) { StringBuilder sb = new StringBuilder(); int k = 0; while (i < s.length()) { char c = s.charAt(i++); if (Character.isDigit(c)) k = k * 10 + (c - '0'); else if (c == '[') { sb.append(decode(s).repeat(k)); k = 0; } // the call stack is the stack else if (c == ']') return sb.toString(); else sb.append(c); } return sb.toString(); }}in the room
How to say it in the interview
talk track
- Ask: can counts have several digits? (Yes — "10[a]".) Can letters appear outside brackets? (Yes.)
- Say: "each '[' saves my current context, each ']' restores it — that's a stack."
- Offer recursion as the same idea with the call stack.
traps
- Reading only one digit for k — "12[a]" becomes "2[a]" after a stray '1'.
- Forgetting to reset k to 0 after pushing it.
what they ask next
Follow-ups
Number of Atoms (LC 726)?
Same stack-of-contexts idea with a map of counts per level; multiply the inner map on ')'.
before you submit
Edge cases to test
- Counts with several digits: "10[x]" (k can be up to 300).
- Letters outside any brackets: "2[abc]3[cd]ef" ends with "ef".
- A tiny input with a huge output: "300[300[a]]" decodes to 90,000 characters.
practise next
Similar problems
- #71Simplify PathMediumin Stacks
- #150Evaluate Reverse Polish NotationMediumin Stacks
- #20Valid ParenthesesEasyin Stacks