验证二叉树的前序序列化
序列化二叉树的一种方法是使用前序遍历。当我们遇到一个非空节点时,我们可以记录下这个节点的值。如果它是一个空节点,我们可以使用一个标记值记录,例如 #。
_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;
};