We have a string where patterns like k[...] mean "repeat whatever is inside the brackets k times." These patterns can be nested. 3[a2[c]] means: first decode the inner 2[c] to get "cc", combine it with the "a" before it to get "acc", and then repeat that whole thing 3 times to get "accaccacc".
The brackets nest the way parentheses nest in mathematical expressions. When we see an opening bracket, we have to set aside what we were building and the multiplier that applies to it, decode the inside, and then come back and apply the multiplier. That save-and-restore pattern is what a stack or recursion provides.
Innermost brackets resolve first, and their result feeds into the outer brackets. A stack matches this inside-out order because the most recently opened bracket is always the first one to close.
1 <= s.length <= 30 → The input is tiny, but the output can be up to 10^5 characters, so the cost is dominated by building the decoded string, not scanning the input.[1, 300] → Repeat counts can be up to 3 digits, so number parsing has to accumulate digits (num = num * 10 + digit) rather than read a single character.s is guaranteed to be valid → No need to handle malformed inputs. Every [ has a matching ], and every [ is preceded by a number.Find the innermost bracket pair (one that contains no other brackets inside it), decode it by repeating its content, splice the result back into the string, and repeat until no brackets remain.
The innermost pair is safe to decode first because its content is plain text with no nested structure. Each substitution removes one bracket pair, so after one pass per pair the string contains no brackets and is fully decoded.
] and then look backwards for its matching [.[ and the string between [ and ].number[string] with the repeated string.Rebuilding the entire string on every pass is wasted work. The next approach decodes everything in a single left-to-right scan.
Instead of repeatedly scanning and replacing, we can process the string in one left-to-right pass using a stack. As we walk through the string, we build the current decoded string character by character. When we hit a [, we save the current string and the pending repeat count by pushing them onto the stack, and start fresh for the inner content. When we hit a ], we pop the saved state, repeat the current string the required number of times, and append it to the saved string.
Two invariants hold at every step of the scan: currentString is the fully decoded text of the innermost bracket still open, and the stack holds one (prefix, count) pair for each enclosing bracket that has not closed yet. Both hold at the start (nothing is open, currentString is empty), and every push and pop preserves them. So when a ] arrives, everything inside it is already decoded, and repeating currentString by the popped count produces correct text at the next level out. Nesting of any depth follows from applying this at every ].
currentString as empty, and currentNum as 0.currentNum = currentNum * 10 + digit (handles multi-digit numbers like 12 or 300).[, push (currentString, currentNum) onto the stack, then reset currentString to empty and currentNum to 0.], pop (previousString, repeatCount) from the stack. Set currentString = previousString + currentString repeated repeatCount times.currentString.currentString.] builds a new string from the saved prefix plus repeated copies of the current string; that result is text that appears in the final output, so its length is at most L.Recursion expresses the same idea without an explicit stack: each recursive call holds the saved state in its own stack frame.
The structure of this problem is inherently recursive. A valid encoded string is either a sequence of regular characters (base case) or a number followed by [encoded_string] where encoded_string is itself a valid encoded string (recursive case).
So we can write a function that processes characters one by one. When it sees a digit, it reads the full number, skips the [, recursively decodes the content up to the matching ], and repeats the result. When it sees a letter, it appends it. A shared index variable, advanced by every call, tells the caller where the recursive call stopped reading.
index that tracks our position in the string.decode():index is within bounds and the current character is not ]:[, recursively decode until ], skip the ], and append the repeated decoded string to result.index.decode() starting at index 0.