题目:请实现两个函数,分别用来序列化和反序列化二叉树。
示例:
你可以将以下二叉树:
1
/ \
2 3
/ \
4 5
序列化为 “[1,2,3,null,null,4,5]”

深度优先搜索,时间复杂度o(n),空间复杂度o(n)

序列化:前序遍历,使用StringBuilder保存节点值

  1. 采用前序遍历的方式,对二叉树的各个节点进行序列化,每个节点值存入一个Stringbuilder中
  2. 存放时,需要在节点值后添加一个!表示节点结束,如果出现了null节点则用#!表示

    1. // Encodes a tree to a single string.
    2. public String serialize(TreeNode root) {
    3. // 存放序列化后的结果
    4. StringBuilder res = new StringBuilder();
    5. helpSerialize(root,res);
    6. return res.toString();
    7. }
    8. public void helpSerialize(TreeNode root,StringBuilder res){
    9. if(root != null){
    10. res.append(root.val).append("!");
    11. }else{
    12. res.append("#!");
    13. return;
    14. }
    15. helpSerialize(root.left,res);
    16. helpSerialize(root.right,res);
    17. }

    反序列化:前序遍历,把StringBuilder中保存的值分割后,重新组成新树

  3. “!”分割成多个字符串,且设置下标index

  4. 每次遇到#时,代表为空,此时index++,且到下一次递归(此处也可以不用下标index,而将数据放到队列中,每次取出队头元素)
  5. 最后用当前值创建新节点,且继续递归左右子树

    1. Integer index = 0;// 反序列化时,当作String数组的下标
    2. // Decodes your encoded data to tree.
    3. public TreeNode deserialize(String data) {
    4. if (data == null || data.length() == 0) return null;
    5. // 拿出有效数据
    6. String[] split = data.split("!");
    7. return helpDeserialize(split);
    8. }
    9. // 全局下标
    10. public TreeNode helpDeserialize(String[] strings){
    11. if(strings[index].equals("#")){
    12. index++;
    13. return null;
    14. }
    15. if(strings.length == index)
    16. return null;
    17. // 当前值作为节点已经被用,index++到达下一个需要反序列化的值
    18. TreeNode node = new TreeNode(Integer.valueOf(strings[index++]));
    19. // 先左
    20. node.left = helpDeserialize(strings);
    21. // 再右
    22. node.right = helpDeserialize(strings);
    23. return node;
    24. }
    25. // 队列形式
    26. public TreeNode deserialize(String data) {
    27. if(data.isEmpty())
    28. return null;
    29. Deque<String> deque = new LinkedList<>(Arrays.asList(data.split("!")));
    30. return helpDeserialize(deque);
    31. }
    32. public TreeNode helpDeserialize(Deque<String> deque){
    33. String str = deque.poll();
    34. if(str.equals("#")){
    35. return null;
    36. }
    37. TreeNode node = new TreeNode(Integer.parseInt(str));
    38. node.left = helpDeserialize(deque);
    39. node.right = helpDeserialize(deque);
    40. return node;
    41. }
    42. }

    广度优先搜索,时间复杂度o(n),空间复杂度o(n)

    序列化:使用队列,按照正常方式,使用StringBuilder保存节点值,如果遇到空,则保存为#!

    1. // Encodes a tree to a single string.
    2. public String serialize(TreeNode root) {
    3. if(root == null)
    4. return "";
    5. StringBuilder sb = new StringBuilder();
    6. Deque<TreeNode> deque = new LinkedList<>();
    7. deque.add(root);
    8. while(!deque.isEmpty()){
    9. int sz = deque.size();
    10. for(int i = 0 ; i < sz ; i++){
    11. TreeNode node = deque.poll();
    12. if(node == null){
    13. sb.append("#!");
    14. continue;
    15. }
    16. sb.append(node.val).append("!");
    17. deque.add(node.left);
    18. deque.add(node.right);
    19. }
    20. }
    21. return sb.toString();
    22. }

    反序列化:前序遍历,把StringBuilder中保存的值分割后,将首个值加入到队列中,然后继续依次根据左右节点加入队列,最后重新组成新树

     // Decodes your encoded data to tree.
     public TreeNode deserialize(String data) {
         if(data.isEmpty())
             return null;
         String [] datas = data.split("!");
         Deque<TreeNode> deque = new LinkedList<>();
         TreeNode root = new TreeNode(Integer.parseInt(datas[0]));
         deque.add(root);
         for(int i = 1 ; i < datas.length ; i++){
             TreeNode node = deque.poll();
             if(!datas[i].equals("#")){
                 TreeNode left = new TreeNode(Integer.parseInt(datas[i]));
                 node.left = left;
                 deque.add(left);
             }
    
             if(!datas[++i].equals("#")){
                 TreeNode right = new TreeNode(Integer.parseInt(datas[i]));
                 node.right = right;
                 deque.add(right);
             }
         }
         return root;
     }