题目:
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
当连续遇到两个‘#’字符时,可以认为找到了一个叶节点,那么可以用一个‘#’来代替 a,'#','#' 对这棵树的结果不会有影响。
分析如下:
"9,3,4,#,#,1,#,#,2,#,6,#,#" 求解过程如下:
9,3,4,#,# ——> 9,3,#
9,3,#,1,#,# ——>9,3,#,# ——>9,#
9,#,2,#,6,#,# ——>9,#,2,#,# ——>9,#,# ——> #
当最后只剩下一个字符‘#’时,认为该字符串是二叉树的前序遍历结果。
class Solution {
public:
bool isValidSerialization(string p) {
//如何serialization the tree and deserialize the code?
stack<string> s;
while(p.size()!=0){
int pos = p.find(',');
string t = p.substr(0,pos);
p = p.substr(pos+1);
if(pos==-1){
t = p;
p = "";
}
string pre = "";
if(!s.empty()) pre = s.top();
s.push(t);
while( pre =="#" && s.top()=="#"){
s.pop();
s.pop();
if(!s.empty() && s.top()!="#"){
s.pop();
if(!s.empty()) pre = s.top();
else pre = "";
s.push("#");
}
else{
s.push("#");
s.push("#");
pre = "";
}
}
}
return s.size()==1 && s.top()=="#";
}
};
第二种想法:考虑树的节点的性质:树的叶节点数 = 树的非叶结点树+1;并且在前序遍历的过程中叶节点树不可能大于非叶结点数。因为最后遍历的一个数为叶节点,所以之前的遍历中,叶节点数<= 非叶结点数
class Solution {
public:
bool isValidSerialization(string preorder) {
istringstream s(preorder);
int node_c = 0, null_c = 0;
string cur;
while (getline(s, cur, ',')) {
if (cur == "#") ++null_c;
else ++node_c;
if (s.good() && null_c == node_c + 1) return false;
}
return null_c == node_c + 1;
}
};
序列化二叉树和反序列化二叉树程序:
#include <stdio.h>
#include "..\Utilities\BinaryTree.h"
#include <iostream>
#include <fstream>
using namespace std;
void Serialize(BinaryTreeNode* pRoot, ostream& stream)
{
if(pRoot == NULL)
{
stream << "$,";
return;
}
stream << pRoot->m_nValue << ',';
Serialize(pRoot->m_pLeft, stream);
Serialize(pRoot->m_pRight, stream);
}
bool ReadStream(istream& stream, int* number)
{
if(stream.eof())
return false;
char buffer[32];
buffer[0] = '\0';
char ch;
stream >> ch;
int i = 0;
while(!stream.eof() && ch != ',')
{
buffer[i++] = ch;
stream >> ch;
}
bool isNumeric = false;
if(i > 0 && buffer[0] != '$')
{
*number = atoi(buffer);
isNumeric = true;
}
return isNumeric;
}
void Deserialize(BinaryTreeNode** pRoot, istream& stream)
{
int number;
if(ReadStream(stream, &number))
{
*pRoot = new BinaryTreeNode();
(*pRoot)->m_nValue = number;
(*pRoot)->m_pLeft = NULL;
(*pRoot)->m_pRight = NULL;
Deserialize(&((*pRoot)->m_pLeft), stream);
Deserialize(&((*pRoot)->m_pRight), stream);
}
}