剑指 Offer 37. 序列化二叉树

Posted lxy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指 Offer 37. 序列化二叉树相关的知识,希望对你有一定的参考价值。

题目链接:剑指 Offer 37. 序列化二叉树

取巧做法

class Codec 
private:
    TreeNode* root;
public:
    // Encodes a tree to a single string.
    string serialize(TreeNode* root) 
        this->root = root;
        return "";
    

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) 
        return this->root;
    
;

方法一:后序遍历实现

解题思路

将树后续遍历为字符串保存,并记录每个节点的左右子树的节点个数,然后取序列最后一个数为根节点,通过其左右子树的节点个数,递归的\\(build\\)其左右子树。

代码

class Codec 
private:
    vector<vector<int>> childNum; // 用于对后序遍历序列进行反序列化过程中判断当前根节点的左右子树集合
public:
    string postorder(TreeNode* root, int &leftNum, int &rightNum) 
        string left, right;
        int child_1_left_num = 0, child_1_right_num = 0;
        int child_2_left_num = 0, child_2_right_num = 0;
        if (root->left) 
            left = postorder(root->left, child_1_left_num, child_1_right_num);
            leftNum ++ ;
        
        if (root->right) 
            right = postorder(root->right, child_2_left_num, child_2_right_num);
            rightNum ++ ;
        
        leftNum += child_1_left_num + child_1_right_num;
        rightNum += child_2_left_num + child_2_right_num;
        childNum.push_back(leftNum, rightNum);
        if (left.length() != 0) left += ",";
        if (right.length() != 0) right += ",";
        return left + right + to_string(root->val);
    

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) 
        if (!root) return "";
        int leftNum = 0, rightNum = 0;
        return postorder(root, leftNum, rightNum);
    

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) 
        if (data.length() == 0) return NULL;
        int n = data.size();
        vector<int> value;
        for (int i = 0, j = 0; i < n; i = j + 1, j = i )  // string转换为数组
            while (j < n) 
                if (data[j] == \',\') break;
                j ++ ;
            
            value.push_back(stoi(data.substr(i, j - i)));
        
        // build tree
        function<TreeNode*(int, int)> build = [&](int l, int r) -> TreeNode* 
            if (l > r) return NULL;
            int mid = l + childNum[r][0] - 1;
            TreeNode* root = new TreeNode(value[r]);
            root->left = build(l, mid);
            root->right = build(mid + 1, r - 1);
            return root;
        ;
        return build(0, value.size() - 1);
    
;

复杂度分析

时间复杂度:\\(O(n)\\)\\(n\\)为节点个数;
空间复杂度:\\(O(n)\\),递归栈空间 和 \\(childNum\\)数组。

方法二:层序遍历实现

解题思路

先对树进行层序遍历,在遍历的过程中,叶子节点的左右空节点也加入序列中;然后在进行层序遍历构造树,维护一个指针\\(i\\),指向当前节点的孩子节点。

代码

class Codec 
public:
    // Encodes a tree to a single string.
    string serialize(TreeNode* root) 
        if (!root) return "";
        string str;
        queue<TreeNode*> q;
        q.push(root);
        while (!q.empty()) 
            TreeNode* front = q.front();
            q.pop();
            if (str.length() != 0) str += ",";
            if (!front) str += "#";
            else 
                str += to_string(front->val);
                q.push(front->left);
                q.push(front->right);
            
        
        return str;
    

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) 
        if (data.length() == 0) return NULL;
        int i = 0, idx = data.find_first_of(",", i);
        TreeNode* root = new TreeNode(stoi(data.substr(i, idx - i)));
        i = idx + 1 ;
        queue<TreeNode*> q;
        q.push(root);
        while (!q.empty()) 
            TreeNode* front = q.front();
            q.pop();
            idx = data.find_first_of(",", i);
            front->left = data.substr(i, idx - i) == "#" ? NULL : new TreeNode(stoi(data.substr(i, idx - i)));
            i = idx + 1;
            idx = data.find_first_of(",", i);
            front->right = data.substr(i, idx - i) == "#" ? NULL : new TreeNode(stoi(data.substr(i, idx - i)));
            i = idx + 1;
            if (front->left != NULL) q.push(front->left);
            if (front->right != NULL) q.push(front->right);
        
        return root;
    
;

复杂度分析

时间复杂度:\\(O(n)\\)\\(n\\)为节点个数;
空间复杂度:\\(O(n)\\),队列空间。

剑指 Offer 37. 序列化二叉树

题目:

剑指 Offer 37. 序列化二叉树 请实现两个函数,分别用来序列化和反序列化二叉树。
示例:
你可以将以下二叉树:
1
/ \
2 3
/ \
4 5

序列化为 "[1,2,3,null,null,4,5]"
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/xu-lie-hua-er-cha-shu-lcof

解题:

关键点:树的层次遍历

 
   
   
 
  1. /**

  2. * 序列化,反序列化树

  3. * 序列化,树转为数组

  4. * 反序列化,数组转为树

  5. * 关键点:树的层次遍历

  6. * 特别注意的一点: 最后一排的子节点的null 也要全部输入哦

  7. * [1,2,3,4,5,null,6,null,null,7,8,null,null,null,null,null,null]

  8. */

  9. public class SerializeTree {


  10. public static void main(String[] args) {

  11. String result = serialize(TreeNode.getTreeRoot());

  12. System.out.println(result);

  13. TreeNode root = deserialize(result);

  14. traverse_level(root);

  15. }


  16. public static void traverse_level(TreeNode root) {

  17. if (root == null) {

  18. System.out.println("当前树是空的!");

  19. }

  20. LinkedList<TreeNode> queue = new LinkedList<>();

  21. queue.add(root);

  22. while (!queue.isEmpty()) {

  23. TreeNode node = queue.poll();

  24. if (node != null) {

  25. System.out.print(node.val + " ");

  26. }

  27. if (node.left != null) {

  28. queue.offer(node.left);

  29. }

  30. if (node.right != null) {

  31. queue.offer(node.right);

  32. }

  33. }

  34. }


  35. // Encodes a tree to a single string.

  36. public static String serialize(TreeNode root) {

  37. if (root == null) {

  38. return "[]";

  39. }

  40. StringBuilder result = new StringBuilder("[");

  41. LinkedList<TreeNode> queue = new LinkedList<>();

  42. queue.offer(root);


  43. while (!queue.isEmpty()) {

  44. TreeNode node = queue.poll();

  45. if (node != null) {

  46. result.append(node.val).append(",");

  47. queue.offer(node.left);

  48. queue.offer(node.right);

  49. } else {

  50. result.append("null").append(",");

  51. }

  52. }

  53. result.deleteCharAt(result.length() - 1);

  54. return result.append("]").toString();

  55. }


  56. // Decodes your encoded data to tree.

  57. // 这里去构建树的时候,一定要注意的是,遍历的是数组,通过数组的下标和树的层次遍历来进行构建;

  58. // 当数组中的元素值 不是null的时候 说明当前节点还有左儿子或者右儿子,应该把儿子放入queue里面;

  59. // 当数组中的元素值 是null的时候 说明当前节点没有了左儿子或者右儿子,不需要进行构建了无需放入到queue里面;

  60. public static TreeNode deserialize(String data) {

  61. if ("[]".equals(data)) {

  62. return null;

  63. }

  64. String[] vals = data.substring(1, data.length() - 1).split(",");

  65. TreeNode root = new TreeNode(Integer.valueOf(vals[0]));


  66. int i = 1;

  67. LinkedList<TreeNode> queue = new LinkedList<>();

  68. queue.add(root);

  69. while (!queue.isEmpty()) {

  70. TreeNode node = queue.poll();

  71. if (!vals[i].equals("null")) { // 如果元素不为空,构建左节点 并放入queue;

  72. node.left = new TreeNode(Integer.valueOf(vals[i]));

  73. queue.offer(node.left);

  74. }

  75. i ++;

  76. if (!vals[i].equals("null")) {// 如果元素不为空,构建右节点 并放入queue;

  77. node.right = new TreeNode(Integer.valueOf(vals[i]));

  78. queue.offer(node.right);

  79. }

  80. i ++;

  81. }


  82. return root;

  83. }

  84. }


以上是关于剑指 Offer 37. 序列化二叉树的主要内容,如果未能解决你的问题,请参考以下文章

剑指 Offer 37. 序列化二叉树

Java 剑指offer(37) 序列化二叉树

LeetCode 剑指 Offer 37. 序列化二叉树

剑指offer 面试37题

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

剑指Offer 37 - 序列化与反序列化二叉树