验证二叉树的前序序列化
难度:
标签:
题目描述
序列化二叉树的一种方法是使用 前序遍历 。当我们遇到一个非空节点时,我们可以记录下这个节点的值。如果它是一个空节点,我们可以使用一个标记值记录,例如 #
。
例如,上面的二叉树可以被序列化为字符串 "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 <= 104
preorder
由以逗号“,”
分隔的[0,100]
范围内的整数和“#”
组成
代码结果
运行时间: 24 ms, 内存: 16.1 MB
/*
* 思路:
* 1. 使用流处理来遍历节点和处理空位计数。
* 2. 同样的逻辑,遇到非空节点时,计数器减1然后增加2,遇到空节点时只需减1。
* 3. 在所有元素遍历完后,计数器应该为0。
*/
import java.util.stream.Stream;
public class Solution {
public boolean isValidSerialization(String preorder) {
int[] slots = {1}; // 初始化空位
// 使用流处理节点
boolean valid = Stream.of(preorder.split(",")).allMatch(node -> {
// 遍历到一个节点,空位-1
slots[0]--;
// 如果空位小于0,说明节点过多,不是有效的序列化
if (slots[0] < 0) return false;
// 非空节点可以提供两个新的空位
if (!node.equals("#")) slots[0] += 2;
return true;
});
// 最终应该没有多余的空位
return valid && slots[0] == 0;
}
}
解释
方法:
该题解使用深度优先搜索(DFS)的思路来验证二叉树的前序序列化是否正确。通过递归遍历序列化字符串,模拟前序遍历的过程。对于每个节点,如果遇到 '#',表示该节点为空,直接返回;否则递归遍历该节点的左右子树。在遍历过程中,使用 pos 变量记录当前遍历的位置,并在递归结束后判断是否正好遍历完整个序列化字符串。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
为什么在遇到'#'时,可以直接返回而不考虑其他元素?
▷🦆
递归遍历时,如果序列化字符串提前结束(即 pos < n 但已无更多节点可遍历),该如何处理?
▷🦆
在实际应用中,如何确保序列化字符串完全被遍历,即 pos 是否总为 n 时算法结束?
▷🦆
如何处理序列化字符串中存在的数字节点,特别是它们的子节点计数和遍历逻辑?
▷