验证二叉树的前序序列化

192 阅读3分钟

验证二叉树的前序序列化

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

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

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

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

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

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

示例 1:

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

示例 2:

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

示例 3:

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

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/ve… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

前序序列化:先输出父树,再输出左子树,再输出右子树

遇到数字,压入栈,代表找到了树,压入栈的树设置为2,因为每个树下面都有两个子树

当一个子树为#时,代表这个子树没有东西,父树-1

当父树为0时,表示下面的两个子树都没东西了,pop出栈

代码

 var isValidSerialization = function (preorder) {
    // 遇到数字,压入栈,代表找到了树,压入栈的树设置为2,因为每个树下面都有两个子树
    // 当一个子树为#时,代表这个子树没有东西,父树-1,
    // 当父树为0时,表示下面的两个子树都没东西了,pop出栈
    let stack = [1];
    let num = 0;
    let Plength = preorder.length;
    while (num < Plength) {
        // 当还没遍历完传进来的二叉树字符串,stack就pop完了,说明这个二叉树是错的
        if(!stack.length) return false;
        if (preorder[num] == ',') {
            // 当找到的是','号,不用管,直接找下一个
            num++;
        }
        else if (preorder[num] == '#') {
            // 当找到的是'#'号,表示树的某个子树为空,树-1
            // 当树=0时,表示这棵树的两个子树都找到了,且都为空,pop出这颗树
            stack[stack.length - 1]--;
            if (stack[stack.length - 1] == 0) stack.pop();
            num++;
        } else {
            // 这个while不是多余的,当preorder[num]为多位数时:'1,2,8,565,11,#,66'的565时
            // 不经过while处理,第一次判断565的5,第二次判断565的6,应该把565当成一个整体
            // 找到565这个数的第一个5时,就 num++ 往后面找,一直找到','号为止
            // 但是这里要控制长度,不然num会一直加下去
            while (num < Plength && preorder[num] !== ',') {
                num++;
            }
            // 当找到数字,代表找到了一个有值的树
            // 这个有值的树又会有两棵子树,所以push2进栈中,但这棵树的父树需要-1,因为父树找到了一颗子树
            stack[stack.length - 1]--;
            stack[stack.length - 1] == 0 ? stack.pop() : '';
            stack.push(2);
        }
    }
    // 当stack的值全都pop出去了,说明这个二叉树是对的
    return !stack.length;
};