1.前序/后序


序列化:使用全局变量stringBuilder

  1. public String serialize(TreeNode root) {
  2. if(root == null) return "";
  3. StringBuilder sb = new StringBuilder();
  4. serializeCore(root,sb);
  5. return sb.toString();
  6. }
  7. String NULL = "#";
  8. String SEP = ",";
  9. public void serializeCore(TreeNode root,StringBuilder sb) {
  10. if(root == null) {
  11. sb.append(NULL).append(SEP);
  12. return;
  13. }
  14. sb.append(root.val).append(SEP); //前序
  15. serializeCore(root.left,sb);
  16. serializeCore(root.right,sb);
  17. // sb.append(root.val).append(SEP); //后序
  18. }

反序列化:使用全局index

  1. public TreeNode deserialize(String data) {
  2. if(data.equals("")) return null;
  3. nodes = data.split(SEP);
  4. return deserializeCore();
  5. }
  6. String[] nodes;
  7. int idx = -1; //Index标记数组已经反序列化的位置 前序
  8. //int idx = nodes.length; // 后序
  9. public TreeNode deserializeCore() {
  10. idx++; //index--;
  11. String parent = nodes[idx];
  12. TreeNode node = null;
  13. if(parent.equals(NULL)){
  14. return node;
  15. }else{
  16. node = new TreeNode(Integer.parseInt(parent));
  17. node.left = deserializeCore();
  18. node.right = deserializeCore();
  19. }
  20. return node;
  21. }

2.层次序列化


使用队列保存左右子树的相对顺序

  1. String SEP = ",";
  2. String NULL = "#";
  3. String serialize(TreeNode root) {
  4. if (root == null) return "";
  5. StringBuilder sb = new StringBuilder();
  6. // 初始化队列,将 root 加入队列
  7. Queue<TreeNode> q = new LinkedList<>();
  8. q.offer(root);
  9. while (!q.isEmpty()) {
  10. TreeNode cur = q.poll();
  11. /* 层级遍历代码位置 */
  12. if (cur == null) {
  13. sb.append(NULL).append(SEP);
  14. continue;
  15. }
  16. sb.append(cur.val).append(SEP);
  17. /*****************/
  18. q.offer(cur.left);
  19. q.offer(cur.right);
  20. }
  21. return sb.toString();
  22. }

反序列化代码框架为BFS

  1. * 将字符串反序列化为二叉树结构 */
  2. TreeNode deserialize(String data) {
  3. if (data.isEmpty()) return null;
  4. String[] nodes = data.split(SEP);
  5. // 第一个元素就是 root 的值
  6. TreeNode root = new TreeNode(Integer.parseInt(nodes[0]));
  7. // 队列 q 记录父节点,将 root 加入队列
  8. Queue<TreeNode> q = new LinkedList<>();
  9. q.offer(root);
  10. for (int i = 1; i < nodes.length; ) {
  11. // 队列中存的都是父节点
  12. TreeNode parent = q.poll();
  13. // 父节点对应的左侧子节点的值
  14. String left = nodes[i++];
  15. if (!left.equals(NULL)) {
  16. parent.left = new TreeNode(Integer.parseInt(left));
  17. q.offer(parent.left);
  18. } else {
  19. parent.left = null;
  20. }
  21. // 父节点对应的右侧子节点的值
  22. String right = nodes[i++];
  23. if (!right.equals(NULL)) {
  24. parent.right = new TreeNode(Integer.parseInt(right));
  25. q.offer(parent.right);
  26. } else {
  27. parent.right = null;
  28. }
  29. }
  30. return root;
  31. }

3.重复子树


给定一棵二叉树,返回所有重复的子树。对于同一类的重复子树,你只需要返回其中任意一棵的根结点即可。 两棵树重复是指它们具有相同的结构以及相同的结点值。 leetcode 652

HashMap + 后序序列化

  1. 通过拼接字符串的方式把二叉树序列化,后序遍历,当序列化整棵树时,子树已经被比较完成
  2. 将子树的序列化结果保存到map中
  3. 如果map中存在相同的序列化子树,则将该子树的根节点加入结果集 ```java class Solution { HashMap dict = new HashMap(); ArrayList res = new ArrayList(); public List findDuplicateSubtrees(TreeNode root) {

     traverse(root);
     return res;
    

    }

    public String traverse(TreeNode root) {

     if(root == null) return "#";
    
     String left = traverse(root.left);
     String right = traverse(root.right);
    
     String strTree =  root.val + ","+left +","+ right;
    
     int cnt = dict.getOrDefault(strTree,0);
    
     if(cnt == 1){  // 只在cnt == 1时,添加到结果集,防止重复
         res.add(root);
     }
    
     dict.put(strTree,cnt+1); 
    
     return strTree;
    

    }

} ```

4.前(后)序,中序构建二叉树