One way to serialize a binary tree is to use pre-order traversal. When we encounter a non-null node, we record the node’s value. If it is a null node, we record using a sentinel value such as
#
._9_ / \ 3 2 / \ / \ 4 1 # 6 / \ / \ / \ # # # # # #For example, the above binary tree can be serialized to the string
"9,3,4,#,#,1,#,#,2,#,6,#,#"
, where#
represents a null node.Given a string of comma separated values, verify whether it is a correct preorder traversal serialization of a binary tree. Find an algorithm without reconstructing the tree.
Each comma separated value in the string must be either an integer or a character
'#'
representingnull
pointer.You may assume that the input format is always valid, for example it could never contain two consecutive commas such as
"1,,3"
.Example 1:
"9,3,4,#,#,1,#,#,2,#,6,#,#"
Returntrue
Example 2:
"1,#"
Returnfalse
Example 3:
"9,#,#,1"
Returnfalse
题目大意:给定一个字符串,判断该字符串是否是一个合法的二叉树序列化串。
思路:
1、在序列串中查找“4,#,#”这样形式的串,并将其替换为“#”。也就是将二叉树中的叶子结点及其后空节点转换为空节点,直至最后整棵树只剩一个空节点。
注意:一定要注意空节点后面跟着若干空节点的情况。
public class Solution {
public boolean isValidSerialization(String preorder) {
if (preorder == null || preorder.length() == 0) {
return false;
}
String[] strs = preorder.split(",");
Stack<String> stack = new Stack<>();
for (String str : strs) {
//注意空节点后面跟着空节点,如:1,#,#,#,#
if (stack.size() == 1 && stack.peek().equals("#")) {
return false;
}
//如果转换后与上一层节点仍然符合转换规则,则继续转换
while (str.equals("#") && stack.size() >= 2 && stack.peek().equals("#")) {
stack.pop();
stack.pop();
}
stack.push(str);
}
return (stack.size() == 1) && (stack.peek().equals("#"));
}
}
2、如果我们把空节点想象成叶子。那么对于每个节点的入度和出度:
(1)空节点#只提供1个入度
(2)非空节点,除根节点外,提供1个入度2个出度
(3)对于整棵树,入度等于出度
我们定义一个变量diff记录出度和入度的差,遇见空节点则diff-1,因为空节点提供一个入度,遇见非空节点先减一再加二。diff不能为负数且最后diff为0,则为合法序列。
public class Solution {
public boolean isValidSerialization(String preorder) {
int diff = 1;//diff = outdegree - indegree
String[] strs = preorder.split(",");
for (String str : strs) {
if (--diff < 0) {
return false;
}
if (!str.equals("#")) {
diff += 2;
}
}
return diff == 0;
}
}
3、在这样的二叉树中,设度为0的节点为n0,度为1的节点为n1,度为2的节点为n2,来看一下空节点的数量和非空节点数量的关系。
空节点数:n0 * 2 + n1
非空节点数:n0+n1+n2
二者差为:n0-n2 = n2+1 – n2 = 1
所以在这颗二叉树中,空节点比非空节点多1。且容易知道合法序列的最后一个字符一定为#。
于是,遍历序列到倒数第二个字符,用count统计,遇到空节点count就减1,遇到非空节点count就加1,过程中count不能出现负数(否则说明空节点下面有非空节点,显然不对)。最后检查count是否为0且最后一个字符是否是#。
public class Solution {
public boolean isValidSerialization(String preorder) {
if (preorder == null || preorder.length() == 0) {
return false;
}
int count = 0;
String[] strs = preorder.split(",");
for (int i = 0; i < strs.length - 1; i++) {
if (strs[i].equals("#")) {
count--;
} else {
count++;
}
if (count < 0) {
return false;
}
}
if (count != 0) {
return false;
}
return strs[strs.length - 1].equals("#");
}
}