算法题解-二叉树的序列化与反序列化

185 阅读4分钟

题目

请对二叉树数据进行序列化和反序列化操作。

输入: root = [1,2,3,null,null,4,5]
输出: [1,2,3,null,null,4,5]

题解

第一种

我们这里声明了两个函数serialize和deserialize,serialize函数接受一个参数root,在函数内部,我们声明了一个变量data,用于存储序列化后的字符串,然后我们声明了一个traverse的嵌套函数,用于遍历二叉树并将节点的值添加到data中,在traverse函数中,我们先进行了一个条件判断,如果root为空,则表示当前节点为空,将字符#添加到data中,并返回,如果root不为空,我们则先递归调用traverse函数遍历左子树,然后再递归调用traverse函数遍历右子树,最后将当前节点的值添加到data中,在serialize函数的末尾,我们调用traverse函数遍历整个二叉树,最后我们返回data字符串,deserialize函数接受一个参数data,表示序列化后的字符串,在函数中我们先将data字符串使用逗号分隔成一个数组,并赋值给变量list,然后我们声明了一个名为traverse的嵌套函数,用于递归地构建二叉树,在traverse函数中,我们先进行了一个条件判断,如果list数组的长度为0,则表示没有节点了则直接返回,然后我们从list数组中弹出最后一个元素,并赋值给变量last,接下来进行条件判断,如果last的值为#,表示当前节点为空,直接返回null,否则我们则创建一个新的TreeNode对象,将last的值作为节点的值,并将左子树和右子树分别递归调用traverse函数构建,最后我们返回构建好的二叉树的根节点,在deserialize函数的末尾,调用traverse函数,传入list数组进行二叉树的构建返回构建好的二叉树的根节点即可

var serialize = function(root) {
    let data = ''
    function traverse(root){
        if(!root) {
            data +='#,'
            return 
        }
        traverse(root.left)
        traverse(root.right)
        data += root.val + ','
    }
    traverse(root)
    return data.slice(0,-1)
};
var deserialize = function(data) {
    let list = data.split(',')
    function traverse(list){
        if(!list.length)return 
        let last = list.pop()
        if(last=='#'){
            return null
        }
        let root = new TreeNode(last,null,null)
        root.right = traverse(list)
        root.left = traverse(list)
        return root
    }
    return traverse(list)
};

第二种

我们这里声明两个函数分别是序列化函数serialize和反序列化函数deserialize,serialize函数中我们先检查根节点root是否为空,如果为空则表示二叉树为空,我们直接返回一个空数组,然后接下来我们声明一个队列queue,并将根节点root入队,在声明一个结果数组res,用于存储序列化后的节点值,我们使用循环,循环条件为当前队列不为空,在循环中我们从队列中取出一个节点cur,进行判断是否为null,如果是则表示该节点为空节点我们就将null添加到结果数组res中,并继续下一次循环,否则我们就将当前节点cur的值cur.val添加到结果数组res中,我们将当前节点cur的左子节点cur.left和右子节点cur.right分别入队,循环结束后,返回结果数组res即可,在deserialize函数中我们先检查输入的数据data是否为空或长度为0,如果是则直接返回null,然后我们在声明一个根节点root,节点的值为数据数组data的第一个元素data[0],在声明一个索引i,并初始化为1,用于遍历数据数组data,接下来声明一个队列queue,并将根节点root入队,我们在使用循环,循环条件为索引i是否小于数据数组data的长度,在循环中我们从队列中取出一个节点cur,如果数据数组data的第i个元素不为null则表示当前节点cur的左子节点不为空,在声明一个新的节点作为当前节点cur的左子节点,并将其入队,我们将索引i增加1,如果数据数组data的第i个元素不为null则表示当前节点cur的右子节点不为空,我们声明一个新的节点作为当前节点cur的右子节点,并将其入队后把索引i增加,当循环结束后,返回根节点root即可

 var serialize = function (root) {
   if(!root){
     return [];
   }
   let queue = [root];
   let res = [];
   while(queue.length){
      let cur = queue.pop();
      if(cur === null){
        res.push(null);
        continue;
      } else {
        res.push(cur.val);
      }
      queue.unshift(cur.left);
      queue.unshift(cur.right);
   }
   return res;
 };
 var deserialize = function (data) {
    if(!data||!data.length){
      return null;
    }
    let root = new TreeNode(data[0]);
    let i = 1;
    let queue = [root];
    while(i<data.length){
      let cur = queue.pop();
      if(data[i]!==null){
        cur.left = new TreeNode(data[i]);
        queue.unshift(cur.left);
      }
      i++;
      if(data[i]!==null){
        cur.right = new TreeNode(data[i]);
        queue.unshift(cur.right);
      }
      i++;
    }
    return root;
 };

坚持努力,无惧未来!