Problem

Design serialize and deserialize methods for a binary tree. Encode to a string, decode back to identical tree.

Example

Input:  [1,2,3,null,null,4,5]
Output: "1,2,#,#,3,4,#,#,5,#,#"

Solution

Pre-order traversal with markers for null nodes. Deserialize using a recursive consumer of tokens.

class Codec:
    def serialize(self, root):
        def helper(node):
            if not node: return ['#']
            return [str(node.val)] + helper(node.left) + helper(node.right)
        return ','.join(helper(root))
    def deserialize(self, data):
        tokens = iter(data.split(','))
        def helper():
            val = next(tokens)
            if val == '#': return None
            node = TreeNode(int(val))
            node.left = helper()
            node.right = helper()
            return node
        return helper()
function serialize(root) {
    const out = [];
    function helper(node) {
        if (!node) { out.push('#'); return; }
        out.push(node.val);
        helper(node.left);
        helper(node.right);
    }
    helper(root);
    return out.join(',');
}
function deserialize(data) {
    const tokens = data.split(',');
    let i = 0;
    function helper() {
        if (tokens[i] === '#') { i++; return null; }
        const node = { val: Number(tokens[i++]), left: null, right: null };
        node.left = helper();
        node.right = helper();
        return node;
    }
    return helper();
}
class Codec {
    void serializeHelper(TreeNode* node, string& s) {
        if (!node) { s += "#,"; return; }
        s += to_string(node->val) + ",";
        serializeHelper(node->left, s);
        serializeHelper(node->right, s);
    }
    TreeNode* deserializeHelper(istringstream& iss) {
        string val;
        getline(iss, val, ',');
        if (val == "#") return nullptr;
        TreeNode* node = new TreeNode(stoi(val));
        node->left = deserializeHelper(iss);
        node->right = deserializeHelper(iss);
        return node;
    }
public:
    string serialize(TreeNode* root) { string s; serializeHelper(root, s); return s; }
    TreeNode* deserialize(string data) { istringstream iss(data); return deserializeHelper(iss); }
};
public class Codec {
    public String serialize(TreeNode root) {
        StringBuilder sb = new StringBuilder();
        helper(root, sb);
        return sb.toString();
    }
    private void helper(TreeNode node, StringBuilder sb) {
        if (node == null) { sb.append("#,"); return; }
        sb.append(node.val).append(',');
        helper(node.left, sb);
        helper(node.right, sb);
    }
    public TreeNode deserialize(String data) {
        Queue<String> q = new LinkedList<>(Arrays.asList(data.split(",")));
        return build(q);
    }
    private TreeNode build(Queue<String> q) {
        String val = q.poll();
        if (val.equals("#")) return null;
        TreeNode node = new TreeNode(Integer.parseInt(val));
        node.left = build(q);
        node.right = build(q);
        return node;
    }
}

Complexity

  • Time: O(n)
  • Space: O(n)

Explanation

Pre-order with null markers preserves the structure unambiguously. The deserializer consumes tokens in the same order they were produced.

Share this article

Comments

Join the discussion. Got a question, found an issue, or want to share your experience?

Leave a Comment

Your email stays private. We just use it for replies.

Nothing to preview yet.

Use **bold**, *italic*, `code`, ```code blocks```, [link](url), > quote, - list