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

Posted xintangchn

tags:

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

力扣链接:https://leetcode-cn.com/problems/xu-lie-hua-er-cha-shu-lcof/

题目描述

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

示例: 

你可以将以下二叉树:

 1
/
2 3
  /
  4 5

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

序列化的形式不定,最终需要达到的效果是deserialize(serialize(root));可以还原原来的树。

 

思路

序列化的顺序显然为层序遍历,因此只需要在层序遍历过程中不断生成序列化字符串即可:

  特殊情况:二叉树为空,返回“[]”

  1. 初始化结果字符串res=""
  2. 层序遍历,同时节点为空则 res+= "#," , 否则res+=`{node.val},`
  3. 用substring方法去掉最后一个“,”
  4. 返回 `[${res}]`

反序列化也类似层序遍历,用同样的逻辑实现一层一层从左至右地建树:

   特殊情况,输入字符串为 "[]", 二叉树为空。

  1. 将字符串按“,”分割成数组nodes(字符串数组)
  2. 取出数组第一个元素,新建为root节点
  3. 新建队列数组queue,并将root入队
  4. 当queue非空:
    1. 取出queue队首,为当前需要处理的节点cur
    2. 取出nodes首元素,为cur的左儿子的值。若不是“#”,新建左儿子节点加入树,并入队列queue。
    3. 取出nodes首元素,为cur的右儿子的值。若不是“#”,新建右儿子节点加入树,并入队列queue。
  5. 返回root

(已经加入树中但儿子节点还没处理完的放在queue里,还没有被处理的放在nodes中,已经建好的节点出队)

 

代码:

/**
 * 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)   return "[]";
    
    let res = "";
    const queue = [root];
    while(queue.length){
        const head = queue.shift();
        if(head){
            res += `${head.val},`;
            queue.push(head.left);
            queue.push(head.right);
        }else{
            res += "#,";
        }
    }
    
    //删去最后一个,
    res = res.substring(0, res.length-1);
    
    return `[${res}]`;
};

/**
 * Decodes your encoded data to tree.
 *
 * @param {string} data
 * @return {TreeNode}
 */
var deserialize = function(data) {
    //"[]"
    if(data.length <= 2) {
        return null;
    }
    
    const nodes = data.substring(1, data.length-1).split(‘,‘);
    const root = new TreeNode(parseInt(nodes.shift()));
    const queue = [root];
    
    while(queue.length){
        const cur = queue.shift();
        const leftVal = nodes.shift();
        if(leftVal !== "#"){
            cur.left = new TreeNode(leftVal);
            queue.push(cur.left);
        }
        
        const rightVal = nodes.shift();
        if(rightVal !== "#"){
            cur.right = new TreeNode(rightVal);
            queue.push(cur.right);
        }
    }
    
    return root;
};

/**
 * Your functions will be called as such:
 * deserialize(serialize(root));
 */

 

时间复杂度: O(N)

空间复杂度:O(N)

 

易错:最后一个","需要单独去掉。

 

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

乱序版 ● 剑指offer每日算法题打卡题解——搜索与回溯算法(题号37,38)

剑指 Offer 37. 序列化二叉树

剑指 Offer 37. 序列化二叉树

剑指offer-37 序列化二叉树

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

剑指offer 面试37题