【二叉树专题】剑指 Offer 37. 序列化二叉树

本问题对应课程链接:剑指offer刷题第七期

要求:

1、请打卡你的解题代码,如果能简单说一下思路则简单说一下思路。
2、给出你代码所用的时间复杂度和空间复杂度

共以下 14 个回答

  • 岱 永久会员 2025年1月9日 下午9:42

    LCR 156. 序列化与反序列化二叉树

    /**
     * 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) {
            if(root==null)return "[]";
            StringBuilder res = new StringBuilder("[");
            Queue<TreeNode> queue = new LinkedList<>();
            queue.add(root);
            while(!queue.isEmpty()){
                TreeNode node = queue.poll();
                if(node!=null){
                    res.append(node.val+",");
                    queue.add(node.left);
                    queue.add(node.right);
                }
                else res.append("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;
            String[] val = data.substring(1,data.length()-1).split(",");
            TreeNode root = new TreeNode(Integer.parseInt(val[0]));
            Queue<TreeNode> queue = new LinkedList<>();
            queue.add(root);
            int i = 1 ;
            while(!queue.isEmpty()){
                TreeNode node = queue.poll();
                if(!val[i].equals("null")){//不为空
                    node.left = new TreeNode(Integer.parseInt(val[i]));
                    queue.add(node.left);
                }
                i++;
                if(!val[i].equals("null")){
                    node.right = new TreeNode(Integer.parseInt(val[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));
    
    0 赞同 0 条回复
  • mpweixin用户 普通 2024年12月24日 下午5:52
    class Codec {
    public:
    
        // Encodes a tree to a single string.
        string serialize(TreeNode* root) {
            string result = "";
            if(root == NULL) return result;
            queue<TreeNode*> q;
            q.push(root);
            while(!q.empty()){
                TreeNode* temp = q.front();
                q.pop();
                if(temp){
                    result += to_string(temp->val) + ",";
                    q.push(temp->left);
                    q.push(temp->right);
                }
                else result += ( "null,");
            }
            return result;
        }
    
        // Decodes your encoded data to tree.
        TreeNode* deserialize(string data) {
            if(data == "") return NULL;
            vector<string> vals;
            string s;
            for(int i=0; i<data.size();i++){
                if(data[i] == ','){
                    vals.push_back(s);
                    s = "";
                }
                else s+=data[i];
            }
            TreeNode* root = new TreeNode(atoi(vals[0].c_str()));
            queue<TreeNode*> q;
            q.push(root);
            int i = 0;
            while(!q.empty()){
                TreeNode* temp = q.front();
                q.pop();
                if(vals[i*2+1] != "null"){
                    temp->left = new TreeNode(atoi(vals[i * 2 + 1].c_str()));
                    q.push(temp->left);
                }
                if(vals[i*2+2] != "null"){
                     temp->right = new TreeNode(atoi(vals[i * 2 + 2].c_str()));
                    q.push(temp->right);
                }
                i++;
            }
            return root;
        }
    };
    

    层序遍历,存储一个完全二叉树,这时可以仅凭一个序列反向还原二叉树

    0 赞同 0 条回复
  • 陆狗陆狗 普通 2024年12月7日 下午3:19

    解题思路
    – 层序遍历是可以原样进行还原的,需要把null节点也存储下来,这样才能知道左右节点谁为null
    – 在序列化时,队列(要放节点)的作用是控制访问顺序(相当于一个跳跃的指针,不是链表或者数组里面指针可以实现的),这个跳跃指针可以按照层序的方式进行访问
    – 在反序列化的时候,队列(要放节点)的作用也是跳跃指针可以按照层序的方式进行访问。那如何找到当前节点的左右节点的值呢?通过数组的指针从左到右去完成。相当于队列负责二叉树的顺序控制,数组的下标负责数组的顺序控制。
    【题解1】

    public class Codec {
    
        // Encodes a tree to a single string.
        public String serialize(TreeNode root) {
            // 通过层序遍历生成字符串
            if (root == null) {
                return null;
            }
            Queue<TreeNode> q = new LinkedList<>();
            q.offer(root);
            StringBuilder build = new StringBuilder();
            while (!q.isEmpty()) {
                TreeNode current = q.poll();
                // null节点也可能会入队
                if (current != null) {
                    build.append(current.val + ",");
                    q.offer(current.left);
                    q.offer(current.right);
                } else {
                    build.append("null,");
                }
            }
            return build.toString();
        }
    
        // Decodes your encoded data to tree.
        public TreeNode deserialize(String data) {
            if (data == null) {
                return null;
            }
            // 解析data为数组
            String[] s = data.split(",");
            Queue<TreeNode> q = new LinkedList<>();
            int i = 0;
            q.offer(new TreeNode(Integer.valueOf(s[i++])));
            TreeNode root = null;
            while (!q.isEmpty()) {
                TreeNode current = q.poll();
                // 根节点
                if (root == null) {
                    root = current;
                }
    
                if (current != null) {
                    // 左节点
                    String val1 =s[i++];
                    // 【错误点1】
                    if (!val1.equals("null")) {
                        current.left = new TreeNode(Integer.valueOf(val1));
                        q.offer(current.left);
                    }
    
                    // 右节点
                    String val2 = s[i++];
                    if (!val2.equals("null")) {
                        current.right = new TreeNode(Integer.valueOf(val2));
                        q.offer(current.right);
                    }
                }
            }
            return root;
    
        }
    }
    
    • 错误点1:比较字符串,要用equals(),不要用
    0 赞同 0 条回复
  • Xiang. 永久会员 2024年12月4日 上午11:30
    思路:看的leetcode评论解答,编码通过层序遍历,存入结点的左右空节点,解码时,假设是满二叉树,根据索引顺序,可知第n个节点,左右子节点依次为2n+1、2n+2,假设出现了空节点,设 m 为列表区间 [0,n] 中的 null 节点个数,那第n个节点对应的子节点就会变为(2n-2m)+1、(2n-2m)+2,每过一个节点,i+2,体现了公式中的2n;节点为空则不加入队列,体现了公式中的-2m.
    public class Codec {
    
        // Encodes a tree to a single string.
        public String serialize(TreeNode root) {
            if(root==null) return "[]";
            StringBuilder sb=new StringBuilder("[");
            Queue<TreeNode> queue=new LinkedList<>();
            queue.offer(root);
            while(!queue.isEmpty()){
                TreeNode tmp=queue.poll();
                if(tmp!=null){
                    queue.offer(tmp.left);
                    queue.offer(tmp.right);
                    sb.append(tmp.val+",");
                }
                else sb.append("null,");
            }
            sb.deleteCharAt(sb.length()-1);
            sb.append("]");
            return sb.toString();
        }
    
        // Decodes your encoded data to tree.
         public TreeNode deserialize(String data) {
            if(data.equals("[]")) return null;
            String[] vals = data.substring(1, data.length() - 1).split(",");
            TreeNode root = new TreeNode(Integer.parseInt(vals[0]));
            Queue<TreeNode> queue = new LinkedList<>() {{ add(root); }};
            int i = 1;
            while(!queue.isEmpty()) {
                TreeNode node = queue.poll();
                if(!vals[i].equals("null")) {
                    node.left = new TreeNode(Integer.parseInt(vals[i]));
                    queue.add(node.left);
                }
                i++;
                if(!vals[i].equals("null")) {
                    node.right = new TreeNode(Integer.parseInt(vals[i]));
                    queue.add(node.right);
                }
                i++;
            }
            return root;
        }
    时间复杂度O(N)
    空间复杂度O(N)
    }
    
    0 赞同 0 条回复
  • Renasc 普通 2024年12月4日 上午11:09

    时间复杂度O(n),空间复杂度O(n)

    public class Codec {
    
        // Encodes a tree to a single string.
        public String serialize(TreeNode root) {
            if (root == null) return "[]";
    
            // 建立队列
            Queue<TreeNode> queue = new LinkedList<>(){{offer(root);}};
            StringBuilder res = new StringBuilder("[");
    
            // 开始遍历
            while (!queue.isEmpty()) {
                TreeNode node = queue.poll();
                if (node != null) {
                    res.append(node.val + ",");
                    queue.offer(node.left);
                    queue.offer(node.right);
                } else {
                    res.append("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;
    
            // 对字符串进行分离
            String[] vals = data.substring(1, data.length()-1).split(",");
    
            // 建立根节点
            TreeNode root = new TreeNode(Integer.parseInt(vals[0]));
    
            // 建立队列
            Queue<TreeNode> queue = new LinkedList<>(){{offer(root);}};
    
            // 定义索引
            int i = 1;
    
            // 遍历队列
            while (i < vals.length) {
                TreeNode node = queue.poll();
                if (!vals[i].equals("null")) {
                    node.left = new TreeNode(Integer.parseInt(vals[i]));
                    queue.offer(node.left);
                }
                i++;
    
                if (!vals[i].equals("null")) {
                    node.right = new TreeNode(Integer.parseInt(vals[i]));
                    queue.offer(node.right);
                }
    
                i++;
            }
            return root;
        }
    }
    
    0 赞同 0 条回复
  • 黑键〰 普通 2024年12月3日 下午5:59
    /**
     * Definition for a binary tree node.
     * function TreeNode(val) {
     *     this.val = val;
     *     this.left = this.right = null;
     * }
     */
    
    /**
     * Encodes a tree to a single string.
     *
     * @param {TreeNode} root
     * @return {string}
     */
    var serialize = function(root) {
        if(root == null) return '';
        let res = '';
        let q = [root]
        while(q.length != 0) {
            let cur = q.shift()
            // 左节点入队
            if(cur != null) {
                q.push(cur.left)
                q.push(cur.right)
                res += cur.val + ','
            } else {
                res += 'null,'
            }
        }
        return res
    };
    
    /**
     * Decodes your encoded data to tree.
     *
     * @param {string} data
     * @return {TreeNode}
     */
    var deserialize = function(data) {
        if(data.length <= 0 || data == null) return null
        let res = data.split(',')
        let head = new TreeNode(parseInt(res[0]))
        let q = [head]
        let i = 1
        while(q.length != 0) {
            let cur = q.shift()
            // 构建左节点
            if(res[i] != 'null') {
                let left = new TreeNode(parseInt(res[i]))
                cur.left = left
                q.push(left)
            }
            i++
            // 构建右节点
            if(res[i] != 'null') {
                let right = new TreeNode(parseInt(res[i]))
                cur.right = right
                q.push(right)
            }
            i++
        }
        return head
    };
    
    /**
     * Your functions will be called as such:
     * deserialize(serialize(root));
     */
    

    思路:跟着视频来看的思路,自己看题的时候这种有点不知道要怎么处理,没理解题目意思。
    层序遍历完成序列化和反序列化

    0 赞同 0 条回复
  • Kisara 普通 2024年12月3日 下午4:39

    先序遍历然后重建二叉树

    /**
     * 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 into a single string.
        public String serialize(TreeNode root) {
            return solveSerialize(root,"");
        }
    
        // Decodes your encoded data to tree.
        public TreeNode deserialize(String data) {
            String[] dataArray=data.split(",");
            List<String> dataList=new LinkedList<String> (Arrays.asList(dataArray));
            return solveDeserialize(dataList);
        }
    
        public String solveSerialize(TreeNode root,String str){
            if(root==null) 
                str+="null,";
            else {
              str+=String.valueOf(root.val) + ",";
              str=solveSerialize(root.left,str);
              str=solveSerialize(root.right,str);
            }
            return str;
        }
    
        public TreeNode solveDeserialize(List<String> data){
                if(data.get(0).equals("null")) {
                    data.remove(0);
                    return null;
                }
                TreeNode root=new TreeNode(Integer.valueOf(data.get(0)));
                data.remove(0);
                root.left=solveDeserialize(data);
                root.right=solveDeserialize(data);
                return root;
        }
    }
    
    // Your Codec object will be instantiated and called as such:
    // Codec codec = new Codec();
    // codec.deserialize(codec.serialize(root));
    

    on on

    0 赞同 0 条回复
  • Aatorx 永久会员 2024年12月3日 下午4:32
    class Codec {
    public:
    
        // Encodes a tree to a single string.
        string serialize(TreeNode* root) {
            if (root == NULL){
                return "";
            }
            ostringstream s;
            queue<TreeNode*> q;
            q.push(root);
            while(!q.empty()){
                TreeNode* temp = q.front();
                q.pop();
                if(temp == NULL){
                    s << "null,";
                }else{
                    s << temp->val << ",";
                    q.push(temp->left);
                    q.push(temp->right);
                }
            }
            return s.str();
        }
    
        // Decodes your encoded data to tree.
        TreeNode* deserialize(string data) {
            if(data.empty()){
                return NULL;
            }
            vector<string> v;
            stringstream ss(data);
            string item;
            while(getline(ss, item, ',')){
                v.push_back(item);
            }
            TreeNode* root = new TreeNode(atoi(v[0].c_str()));
            queue<TreeNode*> q;
            q.push(root);
            int i = 1;
            while(!q.empty() && i < v.size()){
                TreeNode* temp = q.front();
                q.pop();
                if(v[i] != "null"){
                    temp->left = new TreeNode(atoi(v[i].c_str()));
                    q.push(temp->left);
                }
                i++;
                if(v[i] != "null" && i < v.size()){
                    temp->right = new TreeNode(atoi(v[i].c_str()));
                    q.push(temp->right);
                }
                i++;
            }
            return root;
        }
    };
    

    用字符串记录层序遍历结果,null节点也记录,再反向重建二叉树。
    时间复杂度O(N),空间复杂度O(N)。

    0 赞同 0 条回复
  • jaron 普通 2024年12月3日 下午1:31

    利用前序遍历序列化和反序列化

    public class Codec {
    
        // Encodes a tree to a single string.
        public String serialize(TreeNode root) {
            StringBuilder sb = new StringBuilder();
            s(root, sb);
            return sb.toString();
        }
    
        public void s(TreeNode root, StringBuilder sb){
            if(root == null){
                sb.append("#,");
            }else{
                sb.append(root.val).append(",");
                s(root.left, sb);
                s(root.right, sb);
            }
        }
    
        // Decodes your encoded data to tree.
        public TreeNode deserialize(String data) {
            cnt = 0;
            String[] vals = data.split(",");
            return d(vals);
        }
    
        public static int cnt;
    
        public TreeNode d(String[] vals){
            String cur = vals[cnt++];
            if(cur.equals("#")){
                return null;
            }else{
                TreeNode head = new TreeNode(Integer.parseInt(cur));
                head.left = d(vals);
                head.right = d(vals);
                return head;
            }
        }
    }
    
    0 赞同 0 条回复
  • YULONG 永久会员 2024年12月3日 上午4:47
    /**
    解题思路:按先序遍历顺序序列化/反序列化二叉树即可,空节点用null表示
     */
    public class Codec {
    
        String[] preOrder;
        Integer idx;
        static final String nullVal = "null";
    
        // Encodes a tree to a single string.
        public String serialize(TreeNode root) {
            if (root == null){
                return nullVal;
            }
            String val = root.val + "";
            return val + "," + serialize(root.left) + ',' + serialize(root.right);
    
        }
    
        // Decodes your encoded data to tree.
        public TreeNode deserialize(String data) {
            this.preOrder = data.split(",");
            this.idx = 0;
            return deserialize();
        }
    
        public TreeNode deserialize() {
            String val = preOrder[idx];
            idx++;
            if (nullVal.equals(val)){
                return null;
            }
            int value = Integer.parseInt(val);
            TreeNode node = new TreeNode(value);
            node.left = deserialize();
            node.right = deserialize();
            return node;
        }
    
    
    }
    
    0 赞同 0 条回复
  • 迢迢星野 普通 2024年12月2日 下午9:36
    public class Codec {
    
        // 分隔符
        String SEP = ",";
        String NULL = "#";
    
        // Encodes a tree to a single string.
        public String serialize(TreeNode root) {
            // 二叉树转换为字符串
            StringBuilder sb = new StringBuilder();
            traverse(root, sb);
            System.out.println(sb.toString());
            return sb.toString();
        }
    
        private void traverse(TreeNode root, StringBuilder sb) {
            if(root == null) {
                sb.append(NULL).append(SEP);
                return;
            }
    
            // 前序遍历
            sb.append(root.val).append(SEP);
    
            traverse(root.left, sb);
            traverse(root.right, sb);
        }
    
        // Decodes your encoded data to tree.
        public TreeNode deserialize(String data) {
            // 字符串转换为二叉树
            LinkedList<String> nodes = new LinkedList<>();
            for(String s : data.split(SEP)) {
                nodes.addLast(s);
            }
    
            return deserialize(nodes);
        }
    
        private 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;
        }
    }
    

    思路:使用同样的方式遍历二叉树,将其转换为字符串,或是将其转换为二叉树。
    时间复杂度:O(n)
    空间复杂度:O(n)

    0 赞同 0 条回复
  • lQl 永久会员 2024年12月2日 下午9:06

    层序遍历
    时间复杂度O(n)
    空间复杂度O(n)

    /**
     * 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) {
            Queue<TreeNode> q = new LinkedList<>();
            StringBuilder s = new StringBuilder("[");
            if (root == null)
                return "[]";
    
            q.add(root);
            TreeNode node = new TreeNode();
            while (q.size() != 0) {
                node = q.poll();
                if (node != null) {
                    s.append(node.val + ",");
                    q.add(node.left);
                    q.add(node.right);
                } else {
                    s.append("null,");
                }
            }
    
            s.deleteCharAt(s.length() - 1);
            s.append("]");
    
            return s.toString();
        }
    
        // Decodes your encoded data to tree.
        public TreeNode deserialize(String data) {
            if(data.equals("[]"))return null;
            String[] split = data.substring(1,data.length()-1).split(",");
            TreeNode root = new TreeNode(Integer.parseInt(split[0]));
            Queue<TreeNode> q = new LinkedList<>();
            q.add(root);
    
            int i = 1;
            while(!q.isEmpty()){
                TreeNode node = q.poll();
                if(!split[i].equals("null")){
                    node.left = new TreeNode(Integer.parseInt(split[i]));
                    q.add(node.left);
                }
                i++;
                if(!split[i].equals("null")){
                    node.right = new TreeNode(Integer.parseInt(split[i]));
                    q.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));
    
    0 赞同 0 条回复
  • 月下足迹 普通 2024年12月2日 下午8:06

    //前序递归遍历
    public class Codec {

    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        return rserialize(root, "");
    }
    
    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        String[] stringArr = data.split(",");
        List<String> dataList = new LinkedList<>(Arrays.asList(stringArr));
        return rdeserialize(dataList);
    }
    
    private String rserialize(TreeNode root, String str) {
        if (root == null) {
            str += "None,";
        } else {
            str += root.val + ",";
            str = rserialize(root.left, str);
            str = rserialize(root.right, str);
        }
        return str;
    }
    
    private TreeNode rdeserialize(List<String> dataList) {
        if (dataList.get(0).equals("None")) {
            dataList.remove(0);
            return null;
        }
    
        TreeNode root = new TreeNode(Integer.valueOf(dataList.get(0)));
        dataList.remove(0);
        root.left = rdeserialize(dataList);
        root.right = rdeserialize(dataList);
    
        return root;
    }
    

    }

    0 赞同 0 条回复
  • 秋山丽奈 普通 2024年12月2日 下午7:52

    思路: 使用 前序遍历 转为String 在使用前序遍历的方式创建二叉树

    public class Codec {
        List<TreeNode> list = new ArrayList<>();;
    
        // Encodes a tree to a single string.
        public String serialize(TreeNode root) {
            // 前序遍历 记录 
            preOrder(root);
    
            String ans = "";
            for(TreeNode current: list){
                if(current == null){
                    ans += "null";
                }else{
                    ans += current.val;
                }
    
                ans += " ";            
            }
    
            return ans;
    
        }
    
        public void preOrder(TreeNode node){
            if(node == null){
                list.add(null);
                return;
            }
    
            list.add(node);
            preOrder(node.left);
            preOrder(node.right);
        }
    
        // Decodes your encoded data to tree.
        public TreeNode deserialize(String data) {
            String[] spilt = data.split(" ");
    
            return preOrderBuild(spilt);
    
        }
    
        int index = 0;
    
        public TreeNode preOrderBuild(String[] nodeNum){
            if(nodeNum.length == index){
                return null;
            }
    
            if(nodeNum[index].equals("null")){
                return null;
            }else{
                TreeNode current = new TreeNode(Integer.parseInt(nodeNum[index]));
    
                index ++;
                current.left = preOrderBuild(nodeNum);
                index ++;
                current.right = preOrderBuild(nodeNum);
    
                return current;
            }
    
        }
    }
    
    0 赞同 0 条回复

# 回答此问题

后才能回答