Decode String
The drill: Expand a compressed string where k[chunk] means 'repeat chunk k times', and brackets can nest arbitrarily deep — a run-length code that decodes into the full text.
An encoded string arrives using the pattern k[chunk], meaning the chunk inside those brackets repeats k times in the decoded output.
These bracketed groups can nest inside one another to any depth, and a decoded chunk can itself contain more k[...] patterns that need expanding before the outer repeat count applies.
Everything outside the bracket patterns is ordinary text and passes through unchanged. The drill hands back the single fully expanded string once every nested pattern has been unpacked.
- encoded string stays short but nesting can run several levels deep
- repeat counts k are positive integers, always at least 1
- brackets always come in matched, well-formed pairs
- plain letters outside brackets pass through untouched
HINT 1 THE NUDGE
A nested k[...] can't be expanded until everything inside it is fully resolved first. What ordering principle handles 'finish the inner thing before the outer thing' for free?
HINT 2 THE STRUCTURE
Two pieces of state pile up as you go deeper: the text built so far at this level, and the repeat count waiting to multiply whatever comes next. Something needs to hold one frame of both per '['.
HINT 3 ONE STEP FROM THE ANSWER
On '[', push the current string and the current number, then reset both to start fresh. On ']', pop that count and outer string, and set current = outer + count × current. Digits accumulate into a running number; letters just append.
Push the string-so-far and its pending multiplier on '[' ; on ']' pop them and fold count×current back in. Nesting resolves itself.
class Solution:
def decodeString(self, s: str) -> str:
stack = [] # (string built so far, pending multiplier)
current = ""
num = 0
for ch in s:
if ch.isdigit():
num = num * 10 + int(ch)
elif ch == "[":
stack.append((current, num))
current = ""
num = 0
elif ch == "]":
prev, count = stack.pop()
current = prev + current * count
else:
current += ch
return currentclass Solution:
def decodeString(self, s: str) -> str:
while "[" in s:
# the last '[' is always an innermost, unnested bracket
i = s.rindex("[")
j = s.index("]", i)
k = i
while k > 0 and s[k - 1].isdigit():
k -= 1
count = int(s[k:i])
s = s[:k] + s[i + 1 : j] * count + s[j + 1 :]
return sclass Solution {
public String decodeString(String s) {
Deque<String> stringStack = new ArrayDeque<>();
Deque<Integer> countStack = new ArrayDeque<>();
StringBuilder current = new StringBuilder();
int num = 0;
for (char ch : s.toCharArray()) {
if (Character.isDigit(ch)) {
num = num * 10 + (ch - '0');
} else if (ch == '[') {
stringStack.push(current.toString());
countStack.push(num);
current = new StringBuilder();
num = 0;
} else if (ch == ']') {
int count = countStack.pop();
String prev = stringStack.pop();
StringBuilder folded = new StringBuilder(prev);
for (int c = 0; c < count; c++) {
folded.append(current);
}
current = folded;
} else {
current.append(ch);
}
}
return current.toString();
}
}class Solution {
public String decodeString(String s) {
while (s.contains("[")) {
// the last '[' is always an innermost, unnested bracket
int i = s.lastIndexOf("[");
int j = s.indexOf("]", i);
int k = i;
while (k > 0 && Character.isDigit(s.charAt(k - 1))) {
k--;
}
int count = Integer.parseInt(s.substring(k, i));
String chunk = s.substring(i + 1, j);
StringBuilder expanded = new StringBuilder();
for (int c = 0; c < count; c++) {
expanded.append(chunk);
}
s = s.substring(0, k) + expanded + s.substring(j + 1);
}
return s;
}
}✓ CHIP-TIMED — ALL 4 SOLUTIONS RAN GREEN AGAINST SELF-AUTHORED CASES IN CI · JDK 21 · CPYTHON 3.12 · NOTHING PUBLISHES RED