[LeetCode] Verify Preorder Serialization of a Binary Tree 验证二叉树的先序序列化
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:
Input:"9,3,4,#,#,1,#,#,2,#,6,#,#"
Output:true
Example 2:
Input:"1,#"
Output:false
Example 3:
Input:"9,#,#,1"
Output:false
Credits:
Special thanks to @dietpepsi for adding this problem and creating all test cases.
这道题给了我们一个类似序列化二叉树后的字符串,关于二叉树的序列化和去序列化可以参见我之前的博客Serialize and Deserialize Binary Tree,这道题让我们判断给定是字符串是不是一个正确的序列化的二叉树的字符串。那么根据之前那边博客的解法,我们还是要用istringsteam来操作字符串,C++里面没有像Java那样有字符串的split函数,可以直接分隔任意字符串,我们只能使用getline这个函数,来将字符串流的内容都存到一个vector数组中。我们通过举一些正确的例子,比如"9,3,4,#,#,1,#,#,2,#,6,#,#" 或者"9,3,4,#,#,1,#,#,2,#,6,#,#"等等,可以观察出如下两个规律:
1. 数字的个数总是比#号少一个
2. 最后一个一定是#号
那么我们加入先不考虑最后一个#号,那么此时数字和#号的个数应该相同,如果我们初始化一个为0的计数器,遇到数字,计数器加1,遇到#号,计数器减1,那么到最后计数器应该还是0。下面我们再来看两个返回False的例子,"#,7,6,9,#,#,#"和"7,2,#,2,#,#,#,6,#",那么通过这两个反例我们可以看出,如果根节点为空的话,后面不能再有节点,而且不能有三个连续的#号出现。所以我们再加减计数器的时候,如果遇到#号,且此时计数器已经为0了,再减就成负数了,就直接返回False了,因为正确的序列里,任何一个位置i,在[0, i]范围内的#号数都不大于数字的个数的。当循环完成后,我们检测计数器是否为0的同时还要看看最后一个字符是不是#号。参见代码如下:
解法一:
class Solution {
public:
bool isValidSerialization(string preorder) {
istringstream in(preorder);
vector<string> v;
string t = "";
int cnt = ;
while (getline(in, t, ',')) v.push_back(t);
for (int i = ; i < v.size() - ; ++i) {
if (v[i] == "#") {
if (cnt == ) return false;
--cnt;
} else ++cnt;
}
return cnt == && v.back() == "#";
}
};
下面这种解法由网友edyyy提供,不需要建立解法一中的额外数组,而是边解析边判断,遇到不合题意的情况直接返回false,而不用全部解析完再来验证是否合法,提高了运算的效率。我们用一个变量degree表示能容忍的"#"的个数,degree初始化为1。再用一个布尔型变量degree_is_zero来记录degree此时是否为0的状态,这样的设计很巧妙,可以cover到"#"开头,但后面还跟有数字的情况,比如"#,1,2"这种情况,当检测到"#"时,degree自减1,此时若degree为0了,degree_is_zero赋值为true,那么如果后面还跟有其他东西的话,在下次循环开始开始前,先判断degree_is_zero,如果为true的话,直接返回false。而当首字符为数字的话,degree自增1,那么此时degree就成了2,表示后面可以再容忍两个"#"。当循环退出的时候,此时判断degree是否为0,因为我们要补齐"#"的个数,少了也是不对的,参见代码如下:
解法二:
class Solution {
public:
bool isValidSerialization(string preorder) {
istringstream in(preorder);
string t = "";
int degree = ;
bool degree_is_zero = false;;
while (getline(in, t, ',')) {
if (degree_is_zero) return false;
if (t == "#") {
if (--degree == ) degree_is_zero = true;
} else ++degree;
}
return degree == ;
}
};
下面这种解法就更加巧妙了,连字符串解析都不需要了,用一个变量capacity来记录能容忍"#"的个数,跟上面解法中的degree一个作用,然后我们给preorder末尾加一个逗号,这样可以处理末尾的"#"。我们遍历preorder字符串,如果遇到了非逗号的字符,直接跳过,否则的话capacity自减1,如果此时capacity小于0了,直接返回true。此时再判断逗号前面的字符是否为"#",如果不是的话,capacity自增2。这种设计非常巧妙,如果逗号前面是"#",我们capacity自减1没问题,因为容忍了一个"#";如果前面是数字,那么先自减的1,可以看作是初始化的1被减了,然后再自增2,因为每多一个数字,可以多容忍两个"#",最后还是要判断capacity是否为0,跟上面的解法一样,我们要补齐"#"的个数,少了也是不对的,参见代码如下:
解法三:
class Solution {
public:
bool isValidSerialization(string preorder) {
int capacity = ;
preorder += ",";
for (int i = ; i < preorder.size(); ++i) {
if (preorder[i] != ',') continue;
if (--capacity < ) return false;
if (preorder[i - ] != '#') capacity += ;
}
return capacity == ;
}
};
类似题目:
Serialize and Deserialize Binary Tree
参考资料:
https://leetcode.com/problems/verify-preorder-serialization-of-a-binary-tree/
https://discuss.leetcode.com/topic/36035/2-lines-java-using-regex
https://discuss.leetcode.com/topic/45326/c-4ms-solution-o-1-space-o-n-time
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Verify Preorder Serialization of a Binary Tree 验证二叉树的先序序列化的更多相关文章
- 331 Verify Preorder Serialization of a Binary Tree 验证二叉树的前序序列化
序列化二叉树的一种方法是使用前序遍历.当我们遇到一个非空节点时,我们可以记录这个节点的值.如果它是一个空节点,我们可以使用一个标记值,例如 #. _9_ / \ 3 2 ...
- LeetCode Verify Preorder Serialization of a Binary Tree
原题链接在这里:https://leetcode.com/problems/verify-preorder-serialization-of-a-binary-tree/ 题目: One way to ...
- 【LeetCode】331. Verify Preorder Serialization of a Binary Tree 解题报告(Python)
[LeetCode]331. Verify Preorder Serialization of a Binary Tree 解题报告(Python) 标签: LeetCode 题目地址:https:/ ...
- leetcode 331. Verify Preorder Serialization of a Binary Tree
传送门 331. Verify Preorder Serialization of a Binary Tree My Submissions QuestionEditorial Solution To ...
- LeetCode 331. 验证二叉树的前序序列化(Verify Preorder Serialization of a Binary Tree) 27
331. 验证二叉树的前序序列化 331. Verify Preorder Serialization of a Binary Tree 题目描述 每日一算法2019/5/30Day 27LeetCo ...
- 【LeetCode】Verify Preorder Serialization of a Binary Tree(331)
1. Description One way to serialize a binary tree is to use pre-order traversal. When we encounter a ...
- LeetCode OJ 331. Verify Preorder Serialization of a Binary Tree
One way to serialize a binary tree is to use pre-order traversal. When we encounter a non-null node, ...
- Verify Preorder Serialization of a Binary Tree -- LeetCode
One way to serialize a binary tree is to use pre-order traversal. When we encounter a non-null node, ...
- 【leetcode】331. Verify Preorder Serialization of a Binary Tree
题目如下: One way to serialize a binary tree is to use pre-order traversal. When we encounter a non-null ...
随机推荐
- 《HelloGitHub月刊》第09期
<HelloGitHub>第09期 兴趣是最好的老师,<HelloGitHub>就是帮你找到兴趣! 前言 转眼就到年底了,月刊做到了第09期,感谢大家一路的支持和帮助
- Phantomjs+Nodejs+Mysql数据抓取(1.数据抓取)
概要: 这篇博文主要讲一下如何使用Phantomjs进行数据抓取,这里面抓的网站是太平洋电脑网估价的内容.主要是对电脑笔记本以及他们的属性进行抓取,然后在使用nodejs进行下载图片和插入数据库操作. ...
- c#编程基础之字符串函数
c#常用的字符串函数 例一: 获取字符串的大小写函数 ToLower():得到字符串的小写形式 ToUpper():得到字符串的大写形式 注意: 字符串时不可变的,所以这些函数都不会直接改变字符串的内 ...
- vertical-align浅析
一直以来都搞不懂vertical-align,它适用于什么元素,它的对齐规则是什么样的.索性查了下w3c相关规范,发现行高和基线对齐的规范说明里有如下内容: This section is being ...
- SparkStreaming实现Exactly-Once语义
作者:Syn良子 出处:http://www.cnblogs.com/cssdongl 转载请注明出处 译自:http://blog.cloudera.com/blog/2015/03/exactly ...
- C#开发微信门户及应用(8)-微信门户应用管理系统功能介绍
最近对微信接口进行深入的研究,通过把底层接口一步步进行封装后,逐步升级到自动化配置.自动化应答,以及后台处理界面的优化和完善上,力求搭建一个较为完善.适用的微信门户应用管理系统. 微信门户应用管理系统 ...
- EF里单个实体的增查改删以及主从表关联数据的各种增删 改查
本文目录 EF对单个实体的增查改删 增加单个实体 查询单个实体 修改单个实体 删除单个实体 EF里主从表关联数据的各种增删改查 增加(增加从表数据.增加主从表数据) 查询(根据主表找从表数据.根据从表 ...
- Python09作业思路及源码:高级FTP服务器开发(仅供参考)
高级FTP服务器开发 一,作业要求 高级FTP服务器开发 用户加密认证(完成) 多用户同时登陆(完成) 每个用户有不同家目录且只能访问自己的家目录(完成) 对用户进行磁盘配额,不同用户配额可不同(完成 ...
- c语言实现输入一组数自动从大到小排列
#include <stdio.h>main(){ int x; printf("请输入要排序数字个数:"); scanf("%d" ...
- 《连载 | 物联网框架ServerSuperIO教程》- 6.并发通讯模式开发及注意事项
1.C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 <连载 | 物联网框架ServerSuperIO教程>1.4种通讯模式机制. <连载 | 物联网框架Serve ...