题目链接: https://leetcode.com/problems/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:
"9,3,4,#,#,1,#,#,2,#,6,#,#"
Return true
Example 2:
"1,#"
Return false
Example 3:
"9,#,#,1"
Return false
思路: 我的做法是一般的构造二叉树的思路, 就是看:
1. 如果当前结点不为空, 那么说明其必有二个左右子树, 如果数组到当前结点就结束了, 说明其必然不是一个完整的二叉树. 否则再递归的构造其左右子树.
2. 如果当前结点为‘#‘, 说明其是叶子结点, 那么就可以将其返回
最后按照这样的思路看能不能构造成一个二叉树, 如果可以的话, 再看数组结点是不是用完了, 如果没有用完说明结点有剩余, 则整个数组不是一个先序序列.
写完之后仍然觉得不够简洁, 然后看了一个更好的解决方案, 非常聪明的方法! 利用一棵树结点的入度和出度和为0. 就是除了根结点,每一个结点都有一个入度, 非空结点有两个出度.
这样在构造一棵树的时候任何时候都有 出度 >= 入度, 因为只有在补充完所有的空结点之后入度和才等于出度.
所以在任何时候只要 入度 > 出度 , 就说明我们多补充了空结点, 因为空结点只有入度没有出度.
最后遍历完所有结点之后看入度和出度是否相等即可判读是否是一颗完整的序列.
一二份代码是第一种思路,第二份代码是第一份的优化,少了预处理字符串时间复杂度变低,代码可读性降低了,但是思路还是一样的.
各自代码如下:
class Solution { public: void DFS(vector<string>& str, int& index, int& flag) { if(str[index++]=="#") return; if(index+1 >= str.size()) {flag = 0; return;} DFS(str, index, flag); DFS(str, index, flag); } bool isValidSerialization(string preorder) { if(preorder.size()==0) return false; preorder += ","; vector<string> vec; int index = 0, i =0, flag=1; while(i < preorder.size()) { int pos = preorder.find(',', i); vec.push_back(preorder.substr(i, pos-i)); i = pos+1; } DFS(vec, index, flag); return flag==0?false:index==vec.size(); } };
class Solution { public: void DFS(string& str, int& index, int& flag) { if(index >= str.size()) return; while(index<str.size() && str[index] != ',') index++; if(str[(index++) -1]=='#') return; if(str.find(',', index+1) ==string::npos) {flag = 0; return;} DFS(str, index, flag); if(str.find(',', index+1) ==string::npos) {flag = 0; return;} DFS(str, index, flag); } bool isValidSerialization(string preorder) { if(preorder.size()==0) return false; preorder += ","; int flag = 1, index = 0; DFS(preorder, index, flag); return flag==0?false:index==preorder.size(); } };
class Solution { public: bool isValidSerialization(string preorder) { int indegree = -1; preorder += ","; for(int i =0; i < preorder.size(); i++) { if(preorder[i]!=',') continue; indegree++; if(indegree > 0) return false; if(preorder[i-1] != '#') indegree -= 2; } return indegree == 0; } };
第二种参考: https://leetcode.com/discuss/92919/java-counting-indegree-and-outdegree-simple-%26-clear