【剑指offer】37. 序列化二叉树

104 阅读2分钟

题目描述

在这里插入图片描述

在这里插入图片描述

// 37. 序列化二叉树

// 请实现两个函数,分别用来序列化和反序列化二叉树。
// 你可以将以下二叉树:

//     1
//    / \
//   2   3
//      / \
//     4   5

// 序列化为 "[1,2,3,null,null,4,5]"



// 牛客
// 请实现两个函数,分别用来序列化和反序列化二叉树

// 二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格
// 式保存为字符串,从而使得内存中建立
// 起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序
// 的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时
// 通过 某种符号表示空节点(#),以 ! 表示一个结点值的结束(valu
// e!)。

// 二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str
// ,重构二叉树。

// 例如,我们可以把一个只有根节点为1的二叉树序列化为"1,",然后通过自己
// 的函数来解析回这个二叉树

题解

// 这题很难啊,
// 序列化是为了能够完整地保存树的结构信息,这个信息最后可以为
// 反序列化而服务,即根据这个序列化信息完整的还原这个二叉树。
// 按照题意,序列化使用层序遍历的同时需要将null也保存下来。
// 力扣
// 执行用时:23 ms, 在所有 Java 提交中击败了62.32%的用户
// 内存消耗:40.7 MB, 在所有 Java 提交中击败了47.02%的用户
import java.util.LinkedList;
public class Codec {
	
    // 序列化
    public String serialize(TreeNode root) {
		if (root == null)  // 若树为null直接返回"[]"
			return "[]";
		// 创建StringBuilder用于存string结构信息
        StringBuilder res = new StringBuilder();
		// 创建层序遍历要用的队列(用LinkedList模拟)
        LinkedList<TreeNode> q = new LinkedList<>();
        res.append("[");
        q.add(root);
        while(!q.isEmpty()) {
            TreeNode node = q.remove();  // 结点出队即为node
			// 如果遍历当前的node非空,将node.val和逗号","存入res
			// 并将node的左右子结点入队(不管是不是null,因为null我们也要记录)
			if (node != null) {
				res.append(node.val + ",");
				q.add(node.left);
				q.add(node.right);
			}
			else 
				res.append("null,");  // 如果是null,把"null,"存入
        }
		// 存完res末尾会多一个逗号,删掉
		res.deleteCharAt(res.length() - 1);  
        res.append("]");
        // System.out.println(res.toString());
        return res.toString();  // 转String
    }

    // 反序列化
    public TreeNode deserialize(String data) {
		if (data.equals("[]"))  // 如果string是"[]",说明树是null
			return null;
		// 先掐头去尾把中括号"[]"去掉,然后将data中的字符按照逗号分隔
		// 得到字符组vals
		String[] vals = data.substring(1, data.length() - 1).split(",");
		// parseInt将字符串参数解析为有符号的十进制数,即为结点值,
		// 用结点值新建结点作为遍历的第一个点
        TreeNode res = new TreeNode(Integer.parseInt(vals[0]));
		// 初始化队列q,用于构建二叉树,构建过程类似层序遍历
        LinkedList<TreeNode> q = new LinkedList<>();
		q.add(res);
		int i = 1;  // 遍历字符组vals的索引指针i
		// 若q为空(vals中的有效结点遍历完),循环结束
		while (!q.isEmpty()) {
			TreeNode node = q.remove();  // 结点出队
			// 如果vals[i]元素不是null
			if (!vals[i].equals("null")) {
				// 解析结点值新建结点,使node.left指向该结点
				node.left = new TreeNode(Integer.parseInt(vals[i]));
				q.add(node.left);  // 入队
			}
			i++;  // 指针右移
			// 如果下一个vals[i]元素不是null
			if (!vals[i].equals("null")) {
				// 同上
				node.right = new TreeNode(Integer.parseInt(vals[i]));
				q.add(node.right);
			}
			i++;  // 指针右移
		}
		return res;  // 最后返回树
    }
}



// 牛客
// 运行时间:18ms
// 占用内存:10032k
import java.util.LinkedList;
public class Solution {
    String Serialize(TreeNode root) {
        if (root == null)
            return "[]";
        StringBuilder res = new StringBuilder();
        LinkedList<TreeNode> q = new LinkedList<>();
        res.append("[");
        q.add(root);
        while (!q.isEmpty()) {
            TreeNode node = q.remove();
            if (node != null) {
                res.append(node.val + ",");
                q.add(node.left);
                q.add(node.right);
            }
            else
                res.append("null,");
        }
        res.append("]");
        return res.toString();
  }
    TreeNode Deserialize(String str) {
       if (str.equals("[]"))
           return null;
        String[] vals = str.substring(1, str.length() - 1).split(",");
        LinkedList<TreeNode> q = new LinkedList<>();
        TreeNode res = new TreeNode(Integer.parseInt(vals[0]));
        q.add(res);
        int i = 1;
        while (!q.isEmpty()) {
            TreeNode node = q.remove();
            if (!vals[i].equals("null")) {
                node.left = new TreeNode(Integer.parseInt(vals[i]));
                q.add(node.left);
            }
            i++;
            if (!vals[i].equals("null")) {
                node.right = new TreeNode(Integer.parseInt(vals[i]));
                q.add(node.right);
            }
            i++;
        }
        
        return res;
  }
}