Binary Tree Serialisation Lintcode

Design an algorithm and write code to serialize and deserialize a binary tree. Writing the tree to a file is called 'serialization' and reading back from the file to reconstruct the exact same binary tree is 'deserialization'.

 Notice

There is no limit of how you deserialize or serialize a binary tree, LintCode will take your output of serialize as the input of deserialize, it won't check the result of serialize.

Example

An example of testdata: Binary tree {3,9,20,#,#,15,7}, denote the following structure:

  3
 / \
9  20
  /  \
 15   7

Our data serialization use bfs traversal. This is just for when you got wrong answer and want to debug the input.

You can use other method to do serializaiton and deserialization.

 

For this question I used recursion and bfs method to serialize and deserialize. It is not perfect but it works... I don't know... At least accepted by Lintcode...

/**
 * Definition of TreeNode:
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left, right;
 *     public TreeNode(int val) {
 *         this.val = val;
 *         this.left = this.right = null;
 *     }
 * }
 */
class Solution {
    int index = 0;
    /**
     * This method will be invoked first, you should design your own algorithm 
     * to serialize a binary tree which denote by a root node to a string which
     * can be easily deserialized by your own "deserialize" method later.
     */
    public String serialize(TreeNode root) {
        if (root == null) {
            return null;
        }
        StringBuilder str = new StringBuilder();
        helper(root, str);
        return str.toString();
    }
    
    private void helper(TreeNode root, StringBuilder str) {
        if (root == null) {
            str.append("#");
            str.append(",");
            return;
        }
        str.append(root.val);
        str.append(",");
        helper(root.left, str);
        helper(root.right, str);
    }
    
    /**
     * This method will be invoked second, the argument data is what exactly
     * you serialized at method "serialize", that means the data is not given by
     * system, it's given by your own serialize method. So the format of data is
     * designed by yourself, and deserialize it here as you serialize it in 
     * "serialize" method.
     */
    public TreeNode deserialize(String data) {
        if (data == null || data.length() == 0) {
            return null;
        }
        String[] s = data.split(",");
        if (s.length == 0) {
            return null;
        }
        TreeNode root = buildTree(s);
        return root;
        
    }
    private TreeNode buildTree(String[] s) {
        if (index > s.length || s[index].equals("#")) {
            index = index + 1;
            return null;
        }
        TreeNode root = new TreeNode(Integer.valueOf(s[index]));
        index = index + 1;
        root.left = buildTree(s);
        root.right = buildTree(s);
        return root;
    }
}

Then I checked the answer in Jiuzhang, but they used different methods, which is not recursion. Their format is better than mine.

/**
 * Definition of TreeNode:
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left, right;
 *     public TreeNode(int val) {
 *         this.val = val;
 *         this.left = this.right = null;
 *     }
 * }
 */
class Solution {
    int index = 0;
    /**
     * This method will be invoked first, you should design your own algorithm 
     * to serialize a binary tree which denote by a root node to a string which
     * can be easily deserialized by your own "deserialize" method later.
     */
    public String serialize(TreeNode root) {
        if (root == null) {
            return "{}";
        }
        ArrayList<TreeNode> queue = new ArrayList<>();
        queue.add(root);
        for (int i = 0; i < queue.size(); i++) {
            TreeNode n = queue.get(i);
            if (n == null) {
                continue;
            }
            queue.add(n.left);
            queue.add(n.right);
        }
        
        while (queue.get(queue.size() - 1) == null) {
            queue.remove(queue.size() - 1);
        }
        StringBuilder str = new StringBuilder();
        str.append("{");
        str.append(queue.get(0).val);
        for (int i = 1; i < queue.size(); i++) {
            if (queue.get(i) == null) {
                str.append(",#");
            } else {
                str.append(",");
                str.append(queue.get(i).val);
            }
        }
        str.append("}");
        return str.toString();
    }
    
    
    /**
     * This method will be invoked second, the argument data is what exactly
     * you serialized at method "serialize", that means the data is not given by
     * system, it's given by your own serialize method. So the format of data is
     * designed by yourself, and deserialize it here as you serialize it in 
     * "serialize" method.
     */
    public TreeNode deserialize(String data) {
        if (data.equals("{}")) {
            return null;
        }
        String[] s = data.substring(1, data.length() - 1).split(",");
        ArrayList<TreeNode> queue = new ArrayList<>();
        TreeNode node = new TreeNode(Integer.valueOf(s[0]));
        queue.add(node);
        int index = 0;
        boolean isLeft = true;
        for (int i = 1; i < s.length; i++) {
            if (!s[i].equals("#")) {
                TreeNode t = queue.get(index);
                TreeNode tmp = new TreeNode(Integer.valueOf(s[i]));
                if (isLeft) {
                    t.left = tmp;
                } else {
                    t.right = tmp;
                }
                queue.add(tmp);
            }
            if (!isLeft) {
                index++;
            }
            isLeft = !isLeft;
        }
        return node;
        
    }
}

The idea here when serializing is to put nodes in an arraylist layer by layer. When deserializing it is similar.

Notice:

When diserializing, it is smart to use a boolean to check it is left child or right child. And after a left and a right, the index should point to next node.

 

Non-recursion method is not very familiar to me. 还是回顾下吧。。。

posted @ 2017-03-06 04:10  璨璨要好好学习  阅读(138)  评论(0编辑  收藏  举报