题目描述:
序列化二叉树的一种方法是使用前序遍历。当我们遇到一个非空节点时,我们可以记录下这个节点的值。如果它是一个空节点,我们可以使用一个标记值记录,例如 #。
1 | _9_ |
例如,上面的二叉树可以被序列化为字符串 “9,3,4,#,#,1,#,#,2,#,6,#,#”,其中 # 代表一个空节点。
给定一串以逗号分隔的序列,验证它是否是正确的二叉树的前序序列化。编写一个在不重构树的条件下的可行算法。
每个以逗号分隔的字符或为一个整数或为一个表示 null 指针的 ‘#’ 。
你可以认为输入格式总是有效的,例如它永远不会包含两个连续的逗号,比如 “1,,3” 。
示例
示例 1:
输入: “9,3,4,#,#,1,#,#,2,#,6,#,#”
输出: true
示例 2:
输入: “1,#”
输出: false
解法思路:
我们可以利用栈的特性来完成这件事,前序遍历的顺序是中前后。我们可以在栈中记录一个数字,
代表当前节点可能有几个节点。首先我们存入一个1代表根节点。然后我们开始遍历字符串,如果我们遇到”#”就代表这个节点是空节点,我们就需要将栈顶的元素进行减一,代表我们已经找到了一个子节点。如果我们遇到的是数字,就代表当前节点不为空,我们就需要将栈顶的数字进行减一,代表我们已经找到了一个子节点,并且一个不为空的节点可能有两个子节点,所以我们要在栈中再压入一个2.我们需要判断每次遍历栈顶元素是否为0,如果为0代表这个中间节点的两个子节点都找到了,当前节点的遍历完成。要进行出栈操作。到最后我们就判断栈中是否还有元素即可,如果还有说明序列错误。
1 | const isValidSerialization = function (preorder) { |
另外解题思路:每次拆掉⼀个“数字、#、#”的节点(即叶⼦结点),最后树上的全部节点 都会被拆光(即只剩⼀个“#”),能拆光的序列就是合法序列。