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 #.
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 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 such as "1,3"
Example 1:
Input:"9,3,4,#,#,1,#,#,2,#,6,#,#"
Output:true
Example 2:
Input:"1,#"
Output:false
Example 1:
Input:"9,#,#,1"
Output:false
题目大意:
给定一串以逗号分隔的序列,判断它是否是二叉树的前序序列化.编写一个在不重构树的条件下的可行算法.
解题思路:
如果叶子节点是null,那么所有非null的节点(除了root节点)必定有2个出度,1个入度(2个孩子和1个父亲,孩
子可能为空,但是这一题用"#"表示,则肯定存在有2个孩子),所有的null节点只有0个出度,1个入度(0个孩子和
1个父亲).开始构建这棵数,在构建过程中,记录出度和入度之间的差异:dif=out(出度)-in(入度).当下一个节
点到来时候,将dif-1,因为这个节点提供了一个度.如果这个节点不为null,将dif+2,因为提供了两个出度.若序
列化正确,则dif应该永远不会负,并且dif在完成时将变为0.
验证给定的字符串是否为有效的前缀二叉树序列.
需要用到strtok这是c语言的函数.char*类型,printf这是c的语法,不能简单string输出
c++分割字符串还可以直接枚举也可以.
方法二:
stack的思想.
先序遍历中'#'个数总是比数字个数大1个,而且以#结尾.因此在先序遍历字符串数组中去除最后一个字符'#',
则节点个数与'#'个数应该相匹配.任何时候不能出现'#'个数大于节点的个数.设置count统计个数,在遇到数
字时进行+1,遇到'#'时-1.如果此时小于0则返回false,执行完成后判断最后一个字符是否为'#‘.
C++语言实现
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <sstream>
#include <vector>
#include <stack>
using namespace std;
class Solution{
public:
bool isValidSerialization(string preorders){
/*分割字符串*/
char *pre=new char[preorders.size()+1];
strcpy_s(pre,preorders.size()+1,preorders.c_str());/*或者strncpy(pre,orders.c_str(),orders.size()+1)*/
char* str=strtok(pre,",");
vector<string> ans;/*或者vector<char>,下面的push_back(*str)*/
while(str!=nullptr){
ans.push_back(str);
str=strtok(NULL,",");
}
int dif=1;
/*入度+2,出度-1*/
for(auto& c:ans){
dif--;
if(dif<0) return false;
if(c!="#"){
dif+=2;
}
}
return dif==0;
}
bool isValid(string preorder){
/*
vector<string> strs;
int count=0;
for(auto& s:preorder){
in+=s;
count++;
if(s==","){
strs.push_back(in);
in="";
}else{
in+=s;
}
if(count==preorder.size()){
str.push_back(in);//输出最后一个
}
}
*/
stringstream s(preorder);
vector<string> strs;
string in;
while(getline(s,in,'#')){
strs.emplace_back(in);
}
stack<string> res;
for(auto& str:strs){
if(str=="#"){
if(res.empty()){
return false;
}
res.pop();
}else{
res.push(str);
}
}
return strs.back()=="#"&&res.empty();
}
};
int main(int argc,char* argv[]){
string preorders="9,#,92,#,#";//"9,3,4,#,#,1,#,#,2,#,6,#,#";
/*
string in;
for(int i=0;i<=preorders.size();++i){
if(preorders[i]==','||i==preorders.size()){
cout<<i<<" "<<in<<endl;
in="";
}else{
in+=preorders[i];
}
}
*/
//cout<<Solution().isValidSerialization(preorders)<<endl;
return 0;
}
Go语言实现
package main
import (
"fmt"
"strings"
)
func isValidSerialization(preorder string)bool{
nodes,dif:=strings.Split(preorder,","),1
for _,node:=range nodes{
dif--
if dif<0{
return false
}
if node!="#"{
dif+=2
}
}
return dif==0
}
func main(){
preorder:="9,#,92,#,#"//"9,3,4,#,#,1,#,#,2,#,6,#,#"
fmt.Println(isValidSerialization(preorder))
}