offer 37 序列化二叉樹

序列化二叉樹

image.png
一般使用的前序、中序、後序、層序遍歷記錄的二叉樹的信息不完整,即惟一的輸出序列可能對應着多種二叉樹可能性。node

  • 觀察題目示例,序列化的字符串其實是二叉樹的 「層序遍歷」(BFS)結果,本文也採用層序遍歷。

題目分析

image.png
能夠發現規律
image.png
image.png
序列化 使用層序遍歷實現。反序列化 經過以上遞推公式反推各節點在序列中的索引,進而實現。
序列化和反序列化數組

  • Java序列化就是指把Java對象轉換爲字節序列的過程
  • Java反序列化就是指把字節序列恢復爲Java對象的過程。

注意**

  • 爲完整表示二叉樹,考慮將葉節點下的 null 也記錄**
  • stringObject.substring(start,stop):一個新的字符串,該字符串值包含 stringObject 的一個子字符串,其內容是從 start 處到 stop-1 處的全部字符,其長度爲 stop 減 start。 就是座標範圍是左閉右開,不包括stop那個索引對應的字符

題解

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Codec {

    // Encodes a tree to a single string.
    //這個是序列化
    public String serialize(TreeNode root) {
        //利用隊列進行打印,而且須要把null的也打印出來
        if(root == null) return "[]";//要注意方法的返回類型是String
        StringBuilder res = new StringBuilder("[");//定義一個字符串緩衝流先把左側括號加進去
        //定義一個隊列用於加入字符串,而且還要先把根節點加進去,也能夠不加後面單寫一行加
        Queue<TreeNode> queue = new LinkedList<>() {{ add(root); }};
        while(!queue.isEmpty()){
            //poll從隊列頭部刪除一個元素。 隊列是空的時候會返回null
            TreeNode node = queue.poll();
            //若是當前節點不是空的就加入字符串
            if(node != null) {
                //而後出棧的節點的值加入字符緩衝流對象 還要記得加都好,時刻記得這是字符串
                res.append(node.val+",");
                //而後把當前節點的左右節點繼續入棧
                queue.add(node.left);
                queue.add(node.right);
            }else{ res.append("null,");}//若是是空的也要加入null
        }
        //按照層排列完畢了
        res.deleteCharAt(res.length() - 1);//要把最後一個字符串後面一塊兒的那個逗號刪掉
        res.append("]");//刪掉以後再把數組的另外一半字符串加到上面
        return res.toString();//而後再把字符緩衝流變成字符串
        
    }

    // Decodes your encoded data to tree.
    //這個是反序列化
    public TreeNode deserialize(String data) {
        //反序列化就是把輸入的字符串再換成節點
        if(data.equals("[]") ) return null;
        //將輸入的一長串字符串用,裁出來取1是去掉一開始的0索引下的[符號
        String[] str = data.substring(1,data.length() - 1).split(",");
        //由於序列化也是一層一層的,因此第一個字符就是根節點
        TreeNode root = new TreeNode(Integer.parseInt(str[0]));//將字符串裏的數字字符轉化成數字再變成節點
        //定義一個鏈表,先把根節點存進去
        Queue<TreeNode> queue = new LinkedList<>() {{ add(root); }};
        int i = 1;
        while(!queue.isEmpty()){
            //poll從隊列頭部刪除一個元素。 隊列是空的時候會返回null
            TreeNode node = queue.poll();
            //若是下一個字符的值不是null
            if(!str[i].equals("null")){
                //那當前節點的左節點 就是這個值
                node.left = new TreeNode(Integer.parseInt(str[i]));
                //而後再把當前節點的左節點加進去
                queue.add(node.left);
            }
            i++;
            if(!str[i].equals("null")){
                //那當前節點的左節點 就是這個值
                node.right = new TreeNode(Integer.parseInt(str[i]));
                //而後再把當前節點的左節點加進去
                queue.add(node.right);
            }
            i++;
        }
        return root; 
    }
}

// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(root));

還有一個速度比較快的答案,用了遞歸app

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Codec {

    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        StringBuilder sb = new StringBuilder();
        serialize(root, sb);
        return sb.toString();
    }
    public void serialize(TreeNode root, StringBuilder sb){
        if(root == null){
            sb.append("null").append(",");
            return;
        }
        sb.append(root.val).append(",");
        serialize(root.left,sb);
        serialize(root.right,sb);
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        if(data == null || data.length() == 0)  return null;
        String[] s = data.split(",");
        LinkedList<String> nodes = new LinkedList<>();
        for(String str : s){
            nodes.addLast(str);
        }
        return deserialize(nodes);
    }
    public TreeNode deserialize(LinkedList<String> nodes){
        if(nodes.isEmpty()) return null;
        String first = nodes.removeFirst();
        if(first.equals("null")) return null;
        TreeNode root = new TreeNode(Integer.parseInt(first));
        root.left = deserialize(nodes);
        root.right = deserialize(nodes);
        return root;
    }
}

// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(root));
相關文章
相關標籤/搜索