Encode and Decode Strings
Problem Statement
Design an algorithm to encode a list of strings to a string. The encoded string is then sent over the network and is decoded back to the original list of strings.
Please implement encode and decode methods.
Example:
Input: [“lint”, “code”, “love”, “you”]
Output (Encoded): “4#lint4#code4#love3#you”
Output (Decoded): [“lint”, “code”, “love”, “you”]
Note: This is a LeetCode Premium problem, often found on LintCode for free.
Approach: Length Prefixing (Chunked Transfer)
We cannot simply use a special delimiter (like # or ,) to join the strings because the original strings themselves might contain that delimiter! If the input is ["hello#world", "test"], a simple join would result in "hello#world#test", making it impossible to know where the actual string boundaries are during decoding.
To solve this, we prefix each string with its length, followed by a delimiter (like #). This tells the decoder exactly how many characters to read for the string, allowing the string itself to safely contain any characters, including # or numbers.
Encoding Steps:
- Initialize an empty string or array to build the result.
- For every string in the input array, append its length, a
#delimiter, and the string itself. - E.g.,
"lint"becomes"4#lint".
Decoding Steps:
- Use a pointer
istarting at0to traverse the encoded string. - While
iis less than the string length:- Find the next
#character starting fromi. Let’s call its indexj. - The substring from
itojis the integer length of the string. - The actual string starts immediately after the
#(atj + 1) and ends atj + 1 + length. - Extract the substring, add it to your result array, and jump the
ipointer toj + 1 + lengthto process the next string.
- Find the next
Solution
class Solution {
/**
* @param {string[]} strs
* @returns {string}
*/
encode(strs) {
let res = "";
for (let s of strs) {
res += s.length + "#" + s;
}
return res;
}
/**
* @param {string} str
* @returns {string[]}
*/
decode(str) {
const res = [];
let i = 0;
while (i < str.length) {
let j = i;
// Find the delimiter '#'
while (str[j] !== '#') {
j++;
}
// Extract the length prefix
const length = parseInt(str.substring(i, j));
// Extract the actual string
const word = str.substring(j + 1, j + 1 + length);
res.push(word);
// Move pointer to the start of the next encoded string
i = j + 1 + length;
}
return res;
}
}
Complexity Analysis
- Time Complexity: for both
encodeanddecode, where is the total number of characters across all strings. We touch every character essentially once. - Space Complexity: auxiliary space for both methods, although the returned encoded string or decoded array will take space.