LeetCode – Serialize and Deserialize Binary Tree (Java)

Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be deserialized to the original tree structure.

Java Solution 1 – Level Order Traveral

// Encodes a tree to a single string.
public String serialize(TreeNode root) {
    ArrayList<String> list = new ArrayList<>();
    LinkedList<TreeNode> q = new LinkedList<>();
    q.offer(root);
 
    while (!q.isEmpty()) {
        TreeNode h = q.poll();
        if (h == null) {
            list.add("#");
        } else {
            list.add("" + h.val);
            q.offer(h.left);
            q.offer(h.right);
        }
    }
 
    return String.join(",", list);
}
 
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
    String[] arr = data.split(",");
    if (arr[0].equals("#")) {
        return null;
    }
 
    TreeNode root = new TreeNode(Integer.parseInt(arr[0]));
    LinkedList<TreeNode> q = new LinkedList<>();
    q.offer(root);
 
    int i = 1;
 
    while (!q.isEmpty()) {
        TreeNode h = q.poll();
        if (h != null) {
            TreeNode left = null;
            if (!arr[i].equals("#")) {
                left = new TreeNode(Integer.parseInt(arr[i]));
            }
            h.left = left;
            q.offer(left);
            i++;
 
            TreeNode right = null;
            if (!arr[i].equals("#")) {
                right = new TreeNode(Integer.parseInt(arr[i]));
            }
            h.right = right;
            q.offer(right);
            i++;
        }
    }
 
    return root;
}

Java Solution 2 – Preorder Traversal

// Encodes a tree to a single string.
public String serialize(TreeNode root) {
    if(root==null)
        return null;
 
    Stack<TreeNode> stack = new Stack<TreeNode>();
    stack.push(root);
    StringBuilder sb = new StringBuilder();
 
    while(!stack.isEmpty()){
        TreeNode h = stack.pop();   
        if(h!=null){
            sb.append(h.val+",");
            stack.push(h.right);
            stack.push(h.left);  
        }else{
            sb.append("#,");
        }
    }
 
    return sb.toString().substring(0, sb.length()-1);
}
 
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
    if(data == null)
        return null;
 
    int[] t = {0};
    String[] arr = data.split(",");
 
    return helper(arr, t);
}
 
public TreeNode helper(String[] arr, int[] t){
    if(arr[t[0]].equals("#")){
        return null;
    }
 
    TreeNode root = new TreeNode(Integer.parseInt(arr[t[0]]));
 
    t[0]=t[0]+1;
    root.left = helper(arr, t);
    t[0]=t[0]+1;
    root.right = helper(arr, t);
 
    return root;
}

7 thoughts on “LeetCode – Serialize and Deserialize Binary Tree (Java)”

  1. When you have String[] then you don’t need another queue…

    int n = str.length;

    // change # to null
    for (int idx = 0; idx = 0; –idx) {

    if (null == str[idx])
    continue;
    Node cur = new Node(str[idx]);

    int left = 2 * idx + 1;
    int right = left + 1;

    if (left < n) {
    cur.left = new Node(str[left]);
    }

    if (right < n) {
    cur.right = new Node(str[right]);
    }
    }

  2. function Node(val, left, right) {
    this.val = val;
    this.left = left;
    this.right = right;
    }

    var child1 = new Node(1, new Node(4), new Node(10))
    var root = new Node(1, child1, new Node(22, new Node(3)));

    function parseTree(node, arr) {
    var value = node ? node.val : ‘#’;
    arr.push(value);
    if (node) {
    parseTree(node.left, arr);
    parseTree(node.right, arr);
    }
    }

    const arr = [];
    parseTree(root, arr);
    console.log(arr);

    root = new Node(arr[0]);
    let i = 1;
    let node = root;
    while (i < arr.length) {
    const val = arr[i];
    if (val !== '#') {
    const child = new Node(val);
    child.parent= node;
    node[ typeof(node.left) === 'undefined' ? 'left' : 'right'] = child;
    node = child;
    }else{
    // '#' encountered;
    node[typeof(node.left) === 'undefined' ? 'left' : 'right'] = null;
    while(node && typeof(node.left) !== 'undefined' && typeof(node.right) !== 'undefined'){
    node = node.parent;
    }
    }
    i++;
    }

    debugger
    console.log(root);

  3. why have we used an array t of size 1 and increading the value of 0th index, instead of just using a variable and incrementing it..

  4. In the while loop, can we remove queue.offer(null) when string in the arr is “#”? so it doesn’t need to check t=null when we poll element from queue. Is there any reason to add null into the queue?


    while(!queue.isEmpty()){
    TreeNode t = queue.poll();

    if(!arr[i].equals("#")){
    t.left = new TreeNode(Integer.parseInt(arr[i]));
    queue.offer(t.left);
    }else{
    t.left = null;
    }
    i++;

    if(!arr[i].equals("#")){
    t.right = new TreeNode(Integer.parseInt(arr[i]));
    queue.offer(t.right);
    }else{
    t.right = null;
    }
    i++;
    }

  5. t is an array with one element. When the recursion function changed the t inside. The t outside will be modified at the same time. Since they share the same memory space. In another word, the reference t inside is different from the reference t outside, but they point to the same memory space.

  6. I’m confused as to why the second solution works, since java is passed by value how would the T get updated?

Leave a Comment