Decode String — Solution in Python, Java & C++
Decode String solution explained: step-by-step approach, complexity and code in Python, Java, C++ and JavaScript. A medium problem on strings and stack.
Decode String is a medium coding problem on strings, stack and recursion, asked in Nutanix, Yahoo, Yelp and Ola interviews.
- Difficulty: Medium
- Topics: Strings, Stack, Recursion
- Asked at: Nutanix, Yahoo, Yelp, Ola, Razorpay, Hulu
- Time limit: 2 s
- Memory limit: 256 MB
- Languages: JavaScript, TypeScript, Python, Java, C++, C, C#, Go, Kotlin, Swift, Rust, PHP and Ruby
Problem statement
Given an encoded string, return its decoded form. The rule k[encoded_string] means the bracket content is repeated exactly k times. The input is always valid; digits appear only as repeat counts.
Example 1
Input: s = "3[a]2[bc]"
Output: "aaabcbc"
Example 2
Input: s = "3[a2[c]]"
Output: "accaccacc"
Example 3
Input: s = "2[abc]3[cd]ef"
Output: "abcabccdcdcdef"
Constraints
1 <= s.length <= 301 <= k <= 3Nesting depth <= 2; output length <= 300.
Hints for Decode String
Hint 1
Keep two stacks: repeat counts and the string built so far, pushed at every '['.
Hint 2
On ']', pop both and append the repeated inner string to the restored outer one.
How to solve Decode String
k[...] nests, so this is naturally recursive. You can make it iterative by keeping the recursion's saved state yourself: at every [ park the work-in-progress string and the count that is about to apply, then start a fresh string for the inside. At the matching ] the inner string is finished, so multiply it and glue it back onto what you parked.
Approach
- Track
cur, the string being built at the current depth, andnum, the count being read. - On a digit, extend the number with
num = num * 10 + digit— counts can have more than one digit. - On
[, pushnumonto the count stack andcuronto the string stack, then reset both to empty. Everything from here belongs to the inner level. - On
], pop the repeat count and the parked prefix, and setcur = prefix + cur * repeat. The inner level is done and folded into its parent. - On a letter, append it to
cur. When the scan ends,curis the decoded string.
Why it works
The two stacks are the call stack of the recursive version, written out by hand. At a [ everything to the left at that depth is complete and can be set aside; at the matching ] the bracket's content is complete and its multiplier is known, so the expansion can be performed and handed back to the enclosing level. Since brackets are properly nested, pushes and pops pair up exactly, and each level is resolved innermost-first.
Complexity
- Time —
O(total length of the decoded output) - Space —
O(total length of the decoded output)
Pitfalls
- Reset both
numandcurat[. Forgettingcurleaks the outer text into the repeated section. - The popped string is the prefix: it goes before the repeated part, so
prefix + cur * repeat, never the other way round. - Accumulate multi-digit counts with
num * 10 + digit; reading one character as the whole number breaks on counts of 10 or more.
Reference solution
Python
def decodeString(s: str) -> str:
count_st = []
str_st = []
cur = ""
num = 0
for ch in s:
if ch.isdigit():
num = num * 10 + int(ch)
elif ch == "[":
count_st.append(num)
str_st.append(cur)
num = 0
cur = ""
elif ch == "]":
repeat = count_st.pop()
cur = str_st.pop() + cur * repeat
else:
cur += ch
return curJava
public static String decodeString(String s) {
Deque<Integer> countSt = new ArrayDeque<>();
Deque<String> strSt = new ArrayDeque<>();
StringBuilder cur = new StringBuilder();
int num = 0;
for (char ch : s.toCharArray()) {
if (ch >= '0' && ch <= '9') {
num = num * 10 + (ch - '0');
} else if (ch == '[') {
countSt.push(num);
strSt.push(cur.toString());
num = 0;
cur = new StringBuilder();
} else if (ch == ']') {
int repeat = countSt.pop();
StringBuilder rep = new StringBuilder(strSt.pop());
for (int r = 0; r < repeat; r++) rep.append(cur);
cur = rep;
} else {
cur.append(ch);
}
}
return cur.toString();
}C++
string decodeString(string s) {
vector<int> countSt;
vector<string> strSt;
string cur;
int num = 0;
for (char ch : s) {
if (ch >= '0' && ch <= '9') {
num = num * 10 + (ch - '0');
} else if (ch == '[') {
countSt.push_back(num);
strSt.push_back(cur);
num = 0;
cur.clear();
} else if (ch == ']') {
int repeat = countSt.back();
countSt.pop_back();
string prefix = strSt.back();
strSt.pop_back();
string rep;
for (int r = 0; r < repeat; r++) rep += cur;
cur = prefix + rep;
} else {
cur += ch;
}
}
return cur;
}JavaScript
var decodeString = function(s) {
const countSt = [];
const strSt = [];
let cur = "", num = 0;
for (const ch of s) {
if (ch >= "0" && ch <= "9") {
num = num * 10 + (ch.charCodeAt(0) - 48);
} else if (ch === "[") {
countSt.push(num);
strSt.push(cur);
num = 0;
cur = "";
} else if (ch === "]") {
const repeat = countSt.pop();
cur = strSt.pop() + cur.repeat(repeat);
} else {
cur += ch;
}
}
return cur;
};Also on the editorial tab: C, C#, Go, Kotlin, PHP, Ruby, Rust, Swift, TypeScript.
All 515 strings problems · the whole catalogue
Learn the technique: Strings · Stack Data Structure