LeetCode热题(JS版) - 297. 二叉树的序列化与反序列化

113 阅读2分钟

题目描述

请设计一个算法来实现二叉树的序列化与反序列化。

序列化是将一个二叉树转换成字符串形式的表示,从而可以将其存储在文件或者内存中,同时也可以通过网络传输到另一个计算机节点。 序列化时,对于每个节点,我们将其值和左右子节点的值以及指向左右子节点的指针都进行编码。

例如,下面的二叉树:

    1
   / \
  2   3
     / \
    4   5

可以被序列化为字符串 "1,2,null,null,3,4,null,null,5,null,null",我们可以称这个字符串为序列化的字符串,因为它记录了二叉树的遍历顺序。

反序列化是将序列化的字符串反转回原来的二叉树表示。

示例

// Encodes a tree to a single string.
function serialize(root: TreeNode | null): string {}

// Decodes your encoded data to tree.
function deserialize(data: string): TreeNode | null {}

解题思路

序列化

使用BFS(广度优先搜索)遍历二叉树,并将每个节点的值存入数组中,如果该节点存在左子节点或右子节点,则将左子节点或右子节点加入队列中继续往下遍历。当队列为空时,遍历结束,将数组转化成字符串即可。

反序列化

将字符串转换成数组,并将其转化为一个队列。从队列中取出第一个元素作为根节点的值,创建根节点。然后再依次取出队列中的元素,如果该元素不是null,就创建一个新的节点,并将元素的值赋给这个节点。然后将这个节点加入到上一层节点的左子节点或右子节点。 如果节点的左子节点和右子节点都存在,则将该节点出队列,进行下一次循环。

代码实现

class TreeNode {
  val: number;
  left: TreeNode | null;
  right: TreeNode | null;
  constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
    this.val = (val === undefined ? 0 : val);
    this.left = (left === undefined ? null : left);
    this.right = (right === undefined ? null : right);
  }
}

function serialize(root: TreeNode | null): string {
  if (!root) return 'null'; // 空节点返回null
  const queue: Array<TreeNode | null> = [root];
  const res: string[] = [];
  while (queue.length) {
    const node = queue.shift();
    if (node) {
      res.push(node.val.toString());
      queue.push(node.left);
      queue.push(node.right);
    } else {
      // 注意这里
      res.push('null');
    }
  }
  return res.join(',');
};

function deserialize(data: string): TreeNode | null {
  const arr = data.split(',');
  const rootVal = arr.shift();
  if (rootVal === 'null') return null;// 第一个就无效
  
  const root = new TreeNode(parseInt(rootVal!));
  const queue: TreeNode[] = [root];// 还是遍历树
  while (queue.length) {
    const current = queue.shift()!;
    const leftVal = arr.shift();
    const rightVal = arr.shift();
    if (leftVal !== 'null') {
      const leftNode = new TreeNode(parseInt(leftVal!));
      current.left = leftNode;
      queue.push(leftNode);
    }
    if (rightVal !== 'null') {
      const rightNode = new TreeNode(parseInt(rightVal!));
      current.right = rightNode;
      queue.push(rightNode);
    }
  }
  return root;
};

时间/空间复杂度

时间复杂度

  • 序列化:遍历一遍二叉树,时间复杂度为 O(N)O(N)
  • 反序列化:遍历一遍数组,时间复杂度是 O(N)O(N)

所以总的时间复杂度是 $O