力扣 331. 验证二叉树的前序序列化

题目说明

序列化二叉树的一种方法是使用前序遍历。当我们遇到一个非空节点时,我们可以记录下这个节点的值。如果它是一个空节点,我们可以使用一个标记值记录,例如 #

1
2
3
4
5
6
7
     _9_
/ \
3 2
/ \ / \
4 1 # 6
/ \ / \ / \
# # # # # #

例如,上面的二叉树可以被序列化为字符串 "9,3,4,#,#,1,#,#,2,#,6,#,#",其中 # 代表一个空节点。

给定一串以逗号分隔的序列,验证它是否是正确的二叉树的前序序列化。编写一个在不重构树的条件下的可行算法。

每个以逗号分隔的字符或为一个整数或为一个表示 null 指针的 '#'

你可以认为输入格式总是有效的,例如它永远不会包含两个连续的逗号,比如 "1,,3"

示例

例1

1
2
输入: "9,3,4,#,#,1,#,#,2,#,6,#,#"
输出: true

例2

1
2
输入: "1,#"
输出: false

例3

1
2
输入: "9,#,#,1"
输出: false

笔者理解

此题是一道二叉树算法问题,在力扣题库中被定义为中等题。

解法

当笔者阅读完此题后,发现此题运用二叉树的性质可以达到快速解题,二叉树的性质之一:叶子节点数等于非叶子节点数加一让我们来看看具体如何实现的吧。

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public boolean isValidSerialization(String preorder) {
int leafTick = 0;
//标记叶子节点的个数

int nodeTick = 1;
//标记节点总数,预先将根节点算在内

for(char ch: preorder.toCharArray()) {
if(leafTick > (nodeTick - leafTick)) {
return false;
//如果当前遍历得出的叶子节点数大于非叶子节点数,代表当前结构不合理
//例如###这种不可能存在的结构
}
if(ch == ',') { nodeTick++; }
//节点数累加

if(ch == '#') { leafTick++; }
//#代表着空节点,也就是叶子节点,累加
}
return (nodeTick - leafTick) + 1 == leafTick;
//根据二叉树的性质,叶子节点等于非叶子节点数加一,不符合即为不合法树
}

时间和空间效率都很好,可见此解法还比较适合此题;

image.png

总结

本题是今天的每日一题,难度是为中等,感兴趣的朋友都可以去尝试一下,此题还有其他更多的解法,朋友们可以自己逐一尝试。