「这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战」
题目
331. 验证二叉树的前序序列化
序列化二叉树的一种方法是使用前序遍历。当我们遇到一个非空节点时,我们可以记录下这个节点的值。如果它是一个空节点,我们可以使用一个标记值记录,例如 #
。
_9_
/ \
3 2
/ \ / \
4 1 # 6
/ \ / \ / \
# # # # # #
复制代码
例如,上面的二叉树可以被序列化为字符串 "9,3,4,#,#,1,#,#,2,#,6,#,#"
,其中 #
代表一个空节点。
给定一串以逗号分隔的序列,验证它是否是正确的二叉树的前序序列化。编写一个在不重构树的条件下的可行算法。
每个以逗号分隔的字符或为一个整数或为一个表示 null
指针的 '#'
。
你可以认为输入格式总是有效的,例如它永远不会包含两个连续的逗号,比如 "1,,3"
。
示例 1:
输入: "9,3,4,#,#,1,#,#,2,#,6,#,#"
输出: true
复制代码
示例 2:
输入: "1,#"
输出: false
复制代码
示例 3:
输入: "9,#,#,1"
输出: false
复制代码
思路
- 先找规律, 每个节点可以有两个子节点, 但是除了根节点之外,其他的节点每次必须占用一个空位,相当于只增加一个空位;
- 定义变量
prev
用来记录我们可以插入的空位,我们只需要统计循环结束后空位是否刚好为0即可;根节点加两个空位,普通节点加一个空位,"#"节点减一个空位; - 找边界, 一开始得判断根节点是不是空节点,如果是空节点,判断后面是否有剩余元素;
- 如果空位为0, 说明不能插入元素了,这时候后面不能有元素;
实现
function isValidSerialization(preorder) {
let arr = preorder.split(",");
// 只有空的根节点能以"#"开头
if (arr[0] === "#") {
return arr.length === 1;
}
// 根节点已经判断过非空了, 有两个空位
let prev = 2;
const n = arr.length;
for (let i = 1; i < n; i++) {
if (arr[i] === "#") {
prev--;
// 如果没空位了,后面就不能有元素插入了
if (prev === 0) {
return i === n - 1;
}
} else {
prev++;
}
}
return prev === 0;
};
复制代码
看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。