题目描述
序列化二叉树的一种方法是使用前序遍历。
9
/ \
3 2
/ \ / \
4 1 # 6
/ \ / \ / \
# # # # # #
例如,上面的二叉树可以被序列化为字符串 "9,3,4,#,#,1,#,#,2,#,6,#,#"
,其中 #
代表一个空节点。给定一串以逗号分隔的序列,验证它是否是正确的二叉树的前序序列化。编写一个在不重构树的条件下的可行算法。
输入: "9,3,4,#,#,1,#,#,2,#,6,#,#"
输出: true
解题思路
这个题还是推荐用栈模拟,“边的个数”思路不好想。(需要分割字符串split()
的题目用python
更方便)
-
利用前序序列重构树:参考 二叉树的序列化与反序列化的方式,不过此解法不满足题意。
-
边的个数:每个非空节点(非
#
)总能创造出两个边,任何节点都消耗一个边个数。(还可以从出入度之差的角度考虑,最终整颗二叉树的出入度之差为0
,这个思路不太好理解) -
用栈模拟(推荐):使用栈来模拟二叉树的“前序遍历”,就是如果此时栈中的前两层都是
null
(#
),那就将这颗子树弹出去,过程中要判断这棵子树的根节点是否为空,为空直接返回false
,如果不为空将这棵树弹出去之后用一个#
代替,这样一遍遍历下来栈中保留的就应该只有一个#
,对其进行判断,满足返回true
,否则返回false
。(思路要理解)
参考代码
边的解法:带注释C++版
/*
https://www.youtube.com/watch?v=_mbnPPHJmTQ
1.For any tree, number of nodes == number of edges + 1. (so we add 1 to number of edges first)
2.The hashtag(#) should only appear when there's edge available.
Then we have the algorithm or statement:
1.each node consumes 1 edge
2.each non-leaf node creates two edges
3.whenever edges are smaller than 0, return false, which means number of hashtag(#) is too much
4. Finally, edges should be zero to meet the 1st constraint which is number of nodes == number of edges + 1
*/
class Solution {
public:
bool isValidSerialization(string preorder) {
int degree = 1;
string tmp;
stringstream ss;
ss << preorder;
while(getline(ss, tmp, ',')){
degree--;// consume one edge
if(degree<0){
return false;
}
if(tmp[0]!='#'){
degree+=2;// generate 2 edges
}
}
return degree == 0;
}
};
边的解法:python
class Solution:
def isValidSerialization(self, preorder: str) -> bool:
preorder = preorder.split(",")
edges = 1 # 关键
for item in preorder:
edges -= 1
if edges < 0: return False
if item != "#":
edges += 2
return edges == 0
栈模拟:python
class Solution:
def isValidSerialization(self, preorder: str) -> bool:
preorder = preorder.split(",")
stack = []
for item in preorder:
while stack and stack[-1] == "#" and item == "#":
stack.pop()
if not stack:return False
stack.pop()
stack.append(item)
return len(stack) == 1 and stack[0] == "#"