Encode and Decode Strings
Length-prefix framing — encode each string as "len#payload"; decode by parsing the length up to the delimiter, then slicing.
3 min read
string parsing serialization
Problem#
Design encode(list<string>) -> string and decode(string) -> list<string> that round-trip any list of strings.
Examples#
["lint","code","love","you"]→"4#lint4#code4#love3#you"→["lint","code","love","you"].[""]→"0#"→[""].
Constraints#
- Strings may contain any 256 byte values;
1 <= strs.length <= 200, sum of lengths<= 200.
Approach#
Length-prefix each string with its byte count followed by #. Decoding parses digits until #, reads that many bytes as the payload, repeats.
Solution#
class Codec {public: string encode(vector<string>& strs) { string out; for (auto& s : strs) { out += to_string(s.size()); out += '#'; out += s; } return out; } vector<string> decode(string s) { vector<string> out; int i = 0, n = s.size(); while (i < n) { int j = s.find('#', i); int len = stoi(s.substr(i, j - i)); out.push_back(s.substr(j + 1, len)); i = j + 1 + len; } return out; }};import "strconv"
type Codec struct{}
func Constructor() Codec { return Codec{}}
func (c *Codec) Encode(strs []string) string { out := "" for _, s := range strs { out += strconv.Itoa(len(s)) + "#" + s } return out}
func (c *Codec) Decode(s string) []string { out := []string{} i, n := 0, len(s) for i < n { j := i for s[j] != '#' { j++ } length, _ := strconv.Atoi(s[i:j]) out = append(out, s[j+1:j+1+length]) i = j + 1 + length } return out}from typing import List
class Codec: def encode(self, strs: List[str]) -> str: out = [] for s in strs: out.append(f"{len(s)}#{s}") return "".join(out)
def decode(self, s: str) -> List[str]: out = [] i, n = 0, len(s) while i < n: j = s.find('#', i) length = int(s[i:j]) out.append(s[j + 1:j + 1 + length]) i = j + 1 + length return outfunction encode(strs) { let out = ''; for (const s of strs) { out += `${s.length}#${s}`; } return out;}
function decode(s) { const out = []; let i = 0; const n = s.length; while (i < n) { const j = s.indexOf('#', i); const len = parseInt(s.slice(i, j), 10); out.push(s.slice(j + 1, j + 1 + len)); i = j + 1 + len; } return out;}class Codec { public String encode(List<String> strs) { StringBuilder out = new StringBuilder(); for (String s : strs) { out.append(s.length()).append('#').append(s); } return out.toString(); }
public List<String> decode(String s) { List<String> out = new ArrayList<>(); int i = 0, n = s.length(); while (i < n) { int j = s.indexOf('#', i); int len = Integer.parseInt(s.substring(i, j)); out.add(s.substring(j + 1, j + 1 + len)); i = j + 1 + len; } return out; }}function encode(strs: string[]): string { let out = ''; for (const s of strs) { out += `${s.length}#${s}`; } return out;}
function decode(s: string): string[] { const out: string[] = []; let i = 0; const n = s.length; while (i < n) { const j = s.indexOf('#', i); const len = parseInt(s.slice(i, j), 10); out.push(s.slice(j + 1, j + 1 + len)); i = j + 1 + len; } return out;}Editorial#
A length prefix is byte-safe — no escape sequences needed, the delimiter only appears immediately after the digits. Any naive delimiter-only scheme breaks when the data itself contains the delimiter.
Complexity#
- Time:
O(n)for both. - Space:
O(n).
Concept revision#
Related#