题目描述
序列化二叉树的一种方法是使用 前序遍历 。当我们遇到一个非空节点时,我们可以记录下这个节点的值。如果它是一个空节点,我们可以使用一个标记值记录,例如 #
。
例如,上面的二叉树可以被序列化为字符串 "9,3,4,#,#,1,#,#,2,#,6,#,#"
,其中 #
代表一个空节点。
给定一串以逗号分隔的序列,验证它是否是正确的二叉树的前序序列化。编写一个在不重构树的条件下的可行算法。
保证 每个以逗号分隔的字符或为一个整数或为一个表示 null
指针的 '#'
。
你可以认为输入格式总是有效的
- 例如它永远不会包含两个连续的逗号,比如
"1,,3"
。
注意:不允许重建树。
示例 1:
输入: preorder = "9,3,4,#,#,1,#,#,2,#,6,#,#" 输出: true
示例 2:
输入: preorder = "1,#" 输出: false
示例 3:
输入: preorder = "9,#,#,1" 输出: false
提示:
1 <= preorder.length <= 10^4
preorder
由以逗号“,”
分隔的[0,100]
范围内的整数和“#”
组成
1. 思路
我们可以定义一个概念,叫做槽位。一个槽位可以被看作「当前二叉树中正在等待被节点填充」的那些位置。
二叉树的建立也伴随着槽位数量的变化。每当遇到一个节点时:
- 如果遇到了空节点,则要消耗一个槽位;
- 如果遇到了非空节点,则除了消耗一个槽位外,还要再补充两个槽位。
此外,还需要将根节点作为特殊情况处理。
我们使用一个数 cnt 来记录槽位的数量变化。当遇到空节点时,仅将 cnt-- ;当遇到非空节点时,将 cnt 减 1 后,再向加 2(即 cnt ++)。
遍历结束后,若 cnt =0,说明没有待填充的槽位,因此是一个合法序列;否则序列不合法。此外,在遍历的过程中,若槽位数量不足(即 cnt <= 0 ),则序列不合法。
2. 代码
public boolean isValidSerialization(String preorder) {
String[] nodes=preorder.split(",");//获得结点信息
int cnt=1;//槽位数,初始值取1是为了特殊化处理根节点
int length=nodes.length;
for(int i=0;i<length;i++){
if(cnt==0)return false;
if(Objects.equals(nodes[i],"#"))cnt--;
else cnt++;
}
return cnt==0;
}