Encode and Decode Strings

MediumStrings · Serialization🧩 String ManipulationLeetCode #271 ↗Updated

Problem

Design a Codec with two methods: encode turns a List<String> into one string, and decode turns that string back into the exact same list (same order, same contents, empty strings included). The strings may contain any ASCII character, including whatever you might want to use as a separator. Keep no state between calls.
Input["lint","code","love","you"]Output["lint","code","love","you"]
Input["a#b","","3#x"]Output["a#b","","3#x"]

1 ≤ strs.length ≤ 200  ·  0 ≤ strs[i].length ≤ 200  ·  any of the 256 ASCII chars  ·  Follow-up: make it work for any character set.

Try it yourself

Java
class Codec {
    public String encode(List<String> strs) {
        
    }

    public List<String> decode(String s) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
Any separator character can also appear inside the data. Instead of searching for where a string ends, announce its length up front (len#text): the decoder then jumps over the text without reading it.
PatternString Manipulation

Instinct Reading, comparing or rebuilding text character by character? Walk indices on a char[] and build output with a StringBuilder, never with + in a loop.

Memory hack Chars in an array, pointers on the ends, builder at the back - strings are just arrays wearing a costume.

Open the String Manipulation guide →

Approaches

Brute ForceOut-of-Range Sentinel

Time O(n)Space O(n)

Inputs only use chars 0–255, so a char like (char) 257 can never occur in the data. Append it after every string as a terminator and split on it when decoding. A terminator (not a joiner) keeps [] and [""] distinct.

Java
class Codec {
    private static final char END = (char) 257; // never appears in ASCII input

    public String encode(List<String> strs) {
        StringBuilder sb = new StringBuilder();
        for (String s : strs) {
            sb.append(s).append(END);
        }
        return sb.toString();
    }

    public List<String> decode(String s) {
        List<String> out = new ArrayList<>();
        int start = 0;
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == END) {
                out.add(s.substring(start, i));
                start = i + 1;
            }
        }
        return out;
    }
}

Tiny, but correct only because of the ASCII constraint — fails the follow-up.

At a glance

LevelApproachTimeSpace
Brute ForceOut-of-Range SentinelO(n)O(n)
BetterEscape Character + TerminatorO(n)O(n)
OptimalLength Prefix (len#text)O(n)O(n)
Common pitfalls
  • Joining with a plain separator like , or # — breaks as soon as the data contains it.
  • Using a joiner instead of a terminator — [] and [""] both encode to "".
  • In the length-prefix decoder, searching for # from the start of the payload instead of the header.
Interview tips
  • Start by asking what characters can appear; it shows why naive delimiters fail.
  • Test with tricky data: empty strings, strings that look like headers (3#x), an empty list.
  • Mention that this is how HTTP Content-Length and many binary formats frame messages.
Pattern
Length-prefixed framing → serialize variable-length items into one stream when no safe delimiter exists.
My notes saved in this browser