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, 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
方法1: recursion
思路:
本质上是一种自下而上的检查方式。如果用递归的方式,首先根据preorder的性质可以知道当前位置就是root,而要递归求解需要知道left和right的起始位置。为了知道right的起始位置,一定要知道left的size。而为了知道left的size必须遍历到底,遇到“#”才可以返回“1”。而left一定要出现在i + 1的位置,right一定需要出现在i + left + 1的位置,如果没有找到任意一个子树,需要return invalid。
class Solution {
public:
bool isValidSerialization(string preorder) {
string node;
istringstream in(preorder);
vector<string> st;
while (getline(in, node, ',')) st.push_back(node);
if (isValid(st, 0) == st.size()) return true;
return false;
}
int isValid(vector<string> & st, int i) {
if (i >= st.size()) return -1;
if (st[i] == "#") return 1;
bool validFlag = true;
int left = isValid(st, i + 1);
if (left < 0) return -1;
int right = isValid(st, i + left + 1);
if (right < 0) return -1;
return 1 + left + right;
}
};
方法2: stack
思路:
如:”9,3,4,#,#,1,#,#,2,#,6,#,#” 遇到x # #的时候,就把它变为 #
模拟一遍过程:
9,3,4,#,# => 9,3,# 继续读
9,3,#,1,#,# => 9,3,#,# => 9,# 继续读
9,#2,#,6,#,# => 9,#,2,#,# => 9,#,# => #
class Solution(object):
def isValidSerialization(self, preorder):
"""
:type preorder: str
:rtype: bool
"""
stack = []
for node in preorder.split(','):
stack.append(node)
while len(stack) >= 3 and stack[-1] == stack[-2] == '#' and stack[-3] != '#':
stack.pop(), stack.pop(), stack.pop()
stack.append('#')
return len(stack) == 1 and stack.pop() == '#'
reverse iterator, ++it是向前运动。
class Solution {
public:
bool isValidSerialization(string preorder) {
string node;
istringstream in(preorder);
vector<string> st;
while (getline(in, node, ',')) {
st.push_back(node);
while (st.size() >= 3){
auto it= st.rbegin();
string top1 = *it;
string top2 = *(++it);
if (top1 == "#" && top2 == "#" && *(++it) != "#") {
st.pop_back(); st.pop_back(); st.pop_back();
st.push_back("#");
}
else break;
}
}
return st.size() == 1 && st[0] == "#";
}
};