Encode and Decode Strings
Medium · Arrays & Hashing · Explanation and code example
Encoding & Decoding (Optimal)
How it works
Instead of storing all string lengths first and then appending the strings, we can directly attach each string to its length.
For every string, we write length#string.
The # character acts as a clear boundary between the length and the actual content, and using the length ensures we know exactly how many characters to read—no matter what characters appear in the string itself.
During decoding, we simply read characters until we reach # to find the length, then extract exactly that many characters as the string.
This approach is both simpler and more efficient because it avoids building separate sections for lengths and content.
Steps
Encoding
- Initialize an empty result builder (or list of string parts).
- For each string in the list:
- Compute its length.
- Append
"length#string"to the builder.
- Return the final encoded string.
Decoding
- Initialize an empty list for the decoded strings and a pointer
i = 0. - While
iis within the bounds of the encoded string:- Move a pointer
jforward until it finds'#'— this segment represents the length. - Convert the substring
s[i:j]into an integerlength. - Move
ito the character right after'#'. - Extract the next
lengthcharacters — this is the original string. - Append the extracted string to the result list.
- Move
iforward bylengthto continue decoding the next segment.
- Move a pointer
- Return the list of decoded strings.
Complexity
- Time complexity:
O(m + n)for eachencode()anddecode()function calls. - Space complexity:
O(m + n)for eachencode()anddecode()function calls.
Where
mis the sum of lengths of all the strings andnis the number of strings.
Things to watch for
Using a Delimiter That Can Appear in the Strings
Choosing a simple delimiter like a comma or space will break decoding if that character appears inside the original strings. The length-prefixing approach avoids this by using the length to know exactly how many characters to read, making the content irrelevant.
Not Handling Empty Strings or Empty Lists
Edge cases like an empty input list or strings that are themselves empty ("") require careful handling. Ensure your encoding distinguishes between an empty list and a list containing one empty string, and that decoding correctly reconstructs zero-length strings.
Parsing Length Incorrectly for Multi-Digit Numbers
When the length of a string is 10 or more, the length prefix becomes multi-digit. Ensure you read all digits before the # separator rather than just assuming a single digit. Using a loop to collect characters until reaching # handles this correctly.
Python code example
from typing import List
class Solution:
def encode(self, strs: List[str]) -> str:
res = []
for s in strs:
res.append(str(len(s)))
res.append("#")
res.append(s)
return "".join(res)
def decode(self, s: str) -> List[str]:
res = []
i = 0
while i < len(s):
j = i
while s[j] != '#':
j += 1
length = int(s[i:j])
i = j + 1
j = i + length
res.append(s[i:j])
i = j
return res
C++ code example
class Solution {
public:
string encode(vector<string>& strs) {
string res;
for (const string& s : strs) {
res.append(to_string(s.size()));
res.push_back('#');
res.append(s);
}
return res;
}
vector<string> decode(string s) {
vector<string> res;
int i = 0;
while (i < s.size()) {
int j = i;
while (s[j] != '#') {
j++;
}
int length = stoi(s.substr(i, j - i));
i = j + 1;
j = i + length;
res.push_back(s.substr(i, length));
i = j;
}
return res;
}
};
Source and license
Adapted from NeetCode’s source · MIT license. Node types are supplied by LeetCode where needed.