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