[路飞]_验证二叉树的前序序列化 - 栈

217 阅读2分钟

「这是我参与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个元素,格式不正确

这里的替换操作可以通过栈来实现,把序列化的结果转化为数组,每个字符入栈,当:

  1. 栈里元素数量超过3个及以上时,如果第1个和第2个元素为#,第3个元素不为#时是有效叶子节点
  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] === '#'
}

如有错误欢迎指出,欢迎一起讨论!