topic:
One way to serialize a binary tree is to use preorder traversal. When we encounter a non-empty node, we can record the value of this node. If it is an empty node, we can use a tag value record, such as #.
For example, the above binary tree can be serialized into the string "9,3,4,#,#,1,#,#,2,#,6,#,#", where # represents an empty node.
Given a comma-separated sequence, verify that it is the correct preorder serialization of the binary tree. Write a feasible algorithm without reconstructing the tree.
Each comma-separated character is either an integer or a'#' representing a null pointer.
You can think that the input format is always valid, for example it will never contain two consecutive commas, such as "1,,3".
source:
331. Verify the preorder serialization of the binary tree
Problem-solving idea 1: Stack
After reading the question, I was a little confused. I looked at the examples in the question carefully and found that # are all leaf nodes, and the numbers are all non-leaf nodes.
The idea of determination is as follows:
Define a stack to store the number of children of a digital node. The digital node must have 2 children. Loop all nodes:
- When the node is #, the stack ends if it is empty, otherwise a child is added to the top element of the stack;
- When the node is a number, if the stack is empty, it will be pushed directly to the stack, otherwise it will be pushed to the stack after adding a child to the top element of the stack;
- When the top node of the stack has satisfied 2 children, the stack is popped until it is empty or the top node of the stack is not enough for 2 children.
When the stack is empty and there is no node behind, it returns true, other false.
The code is as follows (a bit confusing):
class Solution {
public:
bool isValidSerialization(string preorder) {
stack<int> st;
int i = 0;
while (i < preorder.size()) {
char ch = preorder[i];
while (i < preorder.size() && preorder[i] != ',') i++;
i++;
if (ch == '#') {
if (st.empty()) break;
// top++
int t = st.top();
st.pop();
st.push(t+1);
} else {
// top++
if (!st.empty()) {
int t = st.top();
st.pop();
st.push(t+1);
}
st.push(0);
}
bool end = false;
while (st.top() == 2) {
st.pop();
if (st.empty()) {
end = true;
break;
}
}
if (end) break;
}
return st.empty() && i >= preorder.size();
}
};
Problem-solving idea 2: Use the nature of nodes
Every non-leaf node must have 2 children, so it must be satisfied: the leaf node must have one more than the non-leaf node. In this question, #node is 1 more than number node.
Writing code based on this nature is simple: define the count cnt=1, when # is --, when the number is ++, and when the count is 0, exit, and after exiting, judge whether there are any nodes in the future.
int isValidSerialization(char * preorder){
int cnt = 1;
char *p = preorder;
while (*p != 0) {
if (*p == '#') {
cnt--;
} else {
cnt++;
}
while (*p != 0 && *p != ',') p++;
if (*p == ',') p++;
if (cnt == 0) break;
}
return cnt == 0 && *p == 0;
}