「这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战」
题目
序列化二叉树的一种方法是使用前序遍历。当我们遇到一个非空节点时,我们可以记录下这个节点的值。如果它是一个空节点,我们可以使用一个标记值记录,例如 #
。
力扣(LeetCode):leetcode-cn.com/problems/ve…
解题思路
二叉树的前序遍历是 [根节点 -> 左子树 -> 右子树],叶子节点序列化后为:n,#,#
,如果把每个叶子节点序列化的结果都替换成#
,新的叶子节点做同样的操作,到最后整棵树将只剩下一个#
举个例子
- 正确格式
1,2,#,#,3,#,4,#,# //[2,#,#]替换为[#]
1,#, 3,#,4,#,# //[4,#,#]替换为[#]
1,#, 3,#,# //[3,#,#]替换为[#]
1,#, # //[1,#,#]替换为[#]
# //只剩一个#,格式正确
- 错误格式
1,2,#,3,#,4,#,# //[4,#,#]替换为[#]
1,#,#,3,#,# //[3,#,#]替换为[#]
1,#,#,# //已经不满足替换条件,还有4个元素,格式不正确
这里的替换操作可以通过栈来实现,把序列化的结果转化为数组,每个字符入栈,当:
- 栈里元素数量超过3个及以上时,如果第1个和第2个元素为
#
,第3个元素不为#
时是有效叶子节点 - 如果是有效叶子节点,把3个元素替换成一个
#
,做3次出栈,一次入栈#
- 重复第1、2步操作,直到所有字符入栈
代码实现
var isValidSerialization = function(preorder) {
const stack = []
const arr = preorder.split(',')
let len = 0
arr.forEach(val => {
stack.push(val)
len++
//1.栈里元素数量超过3个及以上时,如果第1个和第2个元素为#,第3个元素不为#时是有效节点
//2.如果是有效叶子节点,把3个元素替换成一个#
//3.重复第1、2步操作
while (len >= 3
&& stack[len - 1] === '#'
&& stack[len - 2] === '#'
&& stack[len - 3] !== '#')
{
stack.pop()
stack.pop()
stack.pop()
stack.push('#')
len -= 2
}
})
//如果最后栈里只剩下一个元素,并且这个元素是#,则表示验证通过
return stack.length === 1 && stack[0] === '#'
}
如有错误欢迎指出,欢迎一起讨论!