Example 1
ready- Input
s = "3[a]2[bc]"- Expected
"aaabcbc"- Why
- repeat 'a' three times, then 'bc' twice
A short instruction can unfold into a wall of text. The challenge is remembering which instruction owns which piece when those instructions nest.
You're given an encoded string s. An encoded group has the form k[encoded], where
k is a positive integer and the text inside the brackets must be repeated k times.
Groups may appear inside other groups. Lowercase letters outside brackets are copied as
they are.
Decode the entire string and return the expanded result.
A few ground rules:
[.1 <= s.length <= 3_000s contains only lowercase English letters, digits, [ and ].k with 1 <= k <= 300.10.100_000.Hints
A closing bracket tells you one complete piece is ready. Expand that piece before attaching it to the text that came before its opening bracket.
When a parser reaches [, it can decode the inner section by calling the same logic
again. The matching ] returns that completed section to its caller.
When [ arrives, save both the repeat count and the partial text built so far. Two
stacks — one for counts and one for prefixes — let you restore both at ].
Could you calculate the decoded length without constructing the decoded string itself?
Visible cases
s = "3[a]2[bc]""aaabcbc"s = "3[a2[c]]""accaccacc"s = "2[abc]3[cd]ef""abcabccdcdcdef"Interview signal
Recursive descent is a parsing method where one function reads a grammar section and
calls itself when it finds a nested section. Here, each call owns the text up to its
matching ].
Read letters into the current section. When a repeat count appears, parse the number,
step over [, recursively decode the inner section, then repeat that result.
def decode_string(s: str) -> str:
index = 0
def parse_section() -> str:
nonlocal index
pieces: list[str] = []
while index < len(s) and s[index] != "]":
if s[index].isalpha():
pieces.append(s[index])
index += 1
continue
repeat = 0
while index < len(s) and s[index].isdigit():
repeat = repeat * 10 + int(s[index])
index += 1
index += 1 # skip '['
inner = parse_section()
index += 1 # skip ']'
pieces.append(inner * repeat)
return "".join(pieces)
return parse_section()With nesting capped at 10, each input character and produced character is copied only a constant number of times.
Time O(n + m), where n is encoded length and m is decoded length. Space O(d + m) for recursion depth d and the output pieces.
You can store the same suspended context explicitly. While scanning:
[ saves the repeat count and the prefix built before this group;] repeats the finished group and attaches it to the saved prefix.def decode_string(s: str) -> str:
counts: list[int] = []
prefixes: list[list[str]] = []
current: list[str] = []
repeat = 0
for char in s:
if char.isdigit():
repeat = repeat * 10 + int(char)
elif char == "[":
counts.append(repeat)
prefixes.append(current)
current = []
repeat = 0
elif char == "]":
group = "".join(current) * counts.pop()
current = prefixes.pop()
current.append(group)
else:
current.append(char)
return "".join(current)The count and prefix stacks always have the same height: each [ pushes one of each,
and its matching ] pops one of each. That pairing is the core correctness invariant.
Time O(n + m) with the fixed depth cap. Space O(n + m) for saved prefixes, counts, and the decoded result.
Ready to run.
3 cases are queued.
Visible testcase
Case 1
Expected
"aaabcbc"