30-leetCode: 331. 验证二叉树的前序序列化

176 阅读2分钟

题目

序列化二叉树的一种方法是使用前序遍历。当我们遇到一个非空节点时,我们可以记录下这个节点的值。如果它是一个空节点,我们可以使用一个标记值记录,例如 #

     _9_
    /   \
   3     2
  / \   / \
 4   1  #  6
/ \ / \   / \
# # # #   # #

例如,上面的二叉树可以被序列化为字符串 "9,3,4,#,#,1,#,#,2,#,6,#,#",其中 # 代表一个空节点。

给定一串以逗号分隔的序列,验证它是否是正确的二叉树的前序序列化。编写一个在不重构树的条件下的可行算法。

每个以逗号分隔的字符或为一个整数或为一个表示 null 指针的 '#' 。

你可以认为输入格式总是有效的,例如它永远不会包含两个连续的逗号,比如 "1,,3" 。

示例

输入: "9,3,4,#,#,1,#,#,2,#,6,#,#"
输出: true

输入: "1,#"
输出: false

输入: "9,#,#,1"
输出: false

解题思路

根据二叉树的特性,每个非空节点下面必有两个节点,那么,定义一个辅助栈stack,初始化有一个值(1);遍历二叉树数组,每个节点都出栈1,如果在出栈之前,stack里面没值了,说明后面的值挂在空节点上,不是二叉树,然后遇到非空节点,给数组push两个值(这里值取1),空节点不管,因为空节点没有子节点。最后,如果stack长度为0 说明是二叉树(入度 = 出度)

/**
 * @param {string} preorder
 * @return {boolean}
 */
var isValidSerialization = function(preorder) {
    // 将字符串转为数组
    const list = preorder.split(',');
    // 定义辅助栈,用来二叉树的出度,入度
    const stack = [1], len = list.length;
    // 遍历二叉树
    for(let i = 0; i < len; i++) {
        // 提前清空了栈,后面有值挂在了空节点上,明显不是二叉树
        if (!stack.length) return false;
        // 不管是不是空节点, 都需要出栈一个值
        stack.pop();
        // 非空节点入栈两个值 
        if(list[i] !== '#') stack.push(1, 1);
    }
    // 遍历完成,栈清空说明是二叉树
    return stack.length === 0;
};