您的位置:首页 > 其它

[leetcode] 331. Verify Preorder Serialization of a Binary Tree

2016-07-21 16:45 369 查看
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 
'#'
 representing 
null
 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,#,#"


Return 
true


Example 2:
"1,#"


Return 
false


Example 3:
"9,#,#,1"


Return 
false


这道题是检验给定序列是否是某个二叉树的前序遍历序列,题目难度为Medium。

可以按照前序遍历二叉树的思路用栈来存储遍历路径上的节点,遇到非‘#’节点时入栈0,表示该节点的左右子树均未填充;遇到‘#’节点时,表明栈顶节点的某个子树为空,将栈顶节点数值加1,表示为空的子树已填充,如果此时数值为2,表明该节点左右子树均填充完毕,将该节点出栈,同时继续将栈顶节点加1进行判断(因为以该节点为根节点的子树已填充完毕),直至栈空或栈顶节点数值小于2。如果栈空时给定序列还没有遍历完毕,表明序列有误,返回false。最终遍历完序列后如果栈空,表明各位置节点顺利填充完毕,返回true。具体代码:class Solution {
public:
bool isValidSerialization(string preorder) {
stack<char> stk;

preorder += ',';
for(int i=0; i<preorder.size(); ++i) {
if(preorder[i] == ',') {
if(preorder[i-1] == '#') {
while(!stk.empty()) {
if(++stk.top() == 2) stk.pop();
else break;
}
if(stk.empty() && i!=preorder.size()-1)
​ ​ ​ ​ ​ ​return false;
}
else {
stk.push(0);
}
}
}

return stk.empty();
}
};还可以通过可放置节点计数来判断序列是否满足条件。初始计数为1,表示可以放入1个根节点,之后遍历序列,每遇到一个节点将计数减1,表示放入一个节点,如果放入的节点不是‘#’,该节点左右子树还可以再放入2个节点,所以将计数加2。遍历过程中计数不能为负数,计数为负时返回false,最终计数为0表示能够放置节点的位置均已放置,满足条件返回true。具体代码:
class Solution {
public:
bool isValidSerialization(string preorder) {
int cnt = 1;
preorder += ',';
for(int i=0; i<preorder.size(); ++i) {
if(preorder[i] == ',') {
if(--cnt < 0) return false;
if(preorder[i-1] != '#') cnt += 2;
}
}
return cnt == 0;
}
};
看了讨论,更理论化的解释是用节点的度来解释的。每个非‘#’节点的入度和出度分别为1和2(除了根节点入度为0),‘#’节点入度和出度分别为1和0,将入度记为-1,出度记为1,则所有节点的入度和出度之和为-1,因为根节点的入度没有出度抵消。将计数初始化为1,以抵消根节点的入度,最终计数为0表示满足条件返回true。同理遍历过程中任何时候计数为负则表示不满足条件返回false。代码和上面是一致的,大家可以按这个思路再看一下。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode