本次刷题日记的第 51 篇,力扣题为:验证二叉树的前序序列化,中等
一、题目描述:
又是一个二叉树的题,二叉树的题怎么地,比多叉树简单吧?其实他们解法都一样
二、这道题考察了什么思想?你的思路是什么?
题目的要求比较明确,就是给出一个字符串,字符串中包含数字,逗号,井号, 分别表示二叉树节点,字符的间隔,以及空节点
然后我们通过某种方式来校验,给出的这一串字符串是符合二叉树的前序遍历的结果
看到这个这个要求其实可能会嘴角一笑,咱们简单的按照前序遍历的方式,将字符串恢复成二叉树是不是就可以了?
但是题目特地强调了一点,咱们不能重建树,因此我们只能另寻他法
分析
稍加思考,我们的注意力可以转移到字符串中某些字符的个数上来,我们看看下图
对于二叉树而言,一个节点可能有 2 个子节点,也有可能是 1 个子节点,那么根据题目中的意思,那么可能是在字符串中补充 具体的两个数字,例如 2,3
或者是 一个空节点 # 号和 1 数字,例如 #,3 或者 3,#
那么当我们去遍历字符串的时候,如果遇到的是 # 号,那么我们就把待补充的节点数减去 1 ,如果是一个数字的话,那么仍然把待补充的节点数减去 1,且在继续补充 2 个节点进去
此处我们可不能直接将上一层的待补充节点数和这一层的待补充节点数混为一谈哦,是需要分开的
这么看来,我们关注的点就是要放在给出的字符串中的字符,我们从头开始遍历,按照上述逻辑进行记录需要补充的字符
我们可以使用栈的方式来处理,继续遍历,如果遇到 # 号,我们就把待补充的节点数(栈顶的数字)减去 1 ,如果是一个数字的话,那么仍然把待补充的节点数减去 1,且在继续补充 2 个节点到栈中
- 在遍历过程中,如果我们还没有遍历完毕题目给出的字符串,可是待补充的节点已经没有了,说明给出字符串是不符合要求的
- 当然,如果遍历完全字符串,发现我们记录的待补充的节点数还有,那么也是有问题的,说明字符串也并不是一个完整的二叉树前序遍历
- 因此,只有当我们完全遍历完字符串,且我们记录的待补充的节点数也是 0 的时候,我们才能判定这个字符串,是一个完整的二叉树前序遍历
三、编码
根据上述逻辑和分析,我们就可以翻译成如下代码
此处需要注意,我们初始化待补充节点的时候,默认给 1 个节点,因为,我们需要放根节点,根节点只有 1 个
编码如下:
func isValidSerialization(preorder string) bool { n := len(preorder) help := []int{1} // 遍历给出的 字符串 for i := 0; i < n; { if len(help) == 0 { return false } // 校验字符串中给出的 3 中情况,数字,逗号,# 号 if preorder[i] == ',' { i++ } else if preorder[i] == '#' { help[len(help)-1]-- if help[len(help)-1] == 0 { help = help[:len(help)-1] } i++ } else { for i < n && preorder[i] != ',' { i++ } help[len(help)-1]-- if help[len(help)-1] == 0 { help = help[:len(help)-1] } help = append(help, 2) } } return len(help) == 0 }
四、总结:
时间复杂度很明确,我们遍历了一遍给出的字符串,因此时间复杂度是 O(n) ,空间复杂度也是 O(n) ,因为咱们开辟了栈空间,这个空间会涉及了二叉树的每一个节点
原题地址:331. 验证二叉树的前序序列化
今天就到这里,学习所得,若有偏差,还请斧正
欢迎点赞,关注,收藏
朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力
好了,本次就到这里
技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。
我是阿兵云原生,欢迎点赞关注收藏,下次见~