LeetCode从先序遍历还原二叉树
题目
我们从二叉树的根节点 root 开始进行深度优先搜索。 在遍历中的每个节点处,我们输出 D 条短划线(其中 D 是该节点的深度),然后输出该节点的值。(如果节点的深度为 D,则其直接子节点的深度为 D + 1。根节点的深度为 0)。 如果节点只有一个子节点,那么保证该子节点为左子节点。 给出遍历输出 S,还原树并返回其根节点 root。
思路
-
先序遍历为根,左,右。 记当前节点为 T T T,上一个节点为 S S S,那么实际上只有两种情况: T T T 是 S S S 的左子节点; T T T 是根节点到 S S S 这一条路径上(不包括 S S S)某一个节点的右子节点。 由于先序遍历的性质,且 T T T 是紧挨 S S S 的后一个,所以 T T T 不可能是 S S S 的右子节点,所以 T T T 只有可能是 S S S 的祖辈节点的右子节点 在遍历字符串,确定节点深度和数值的同时维护一个栈,用来存储等待构建子树的父节点。由于先序遍历的先左后右,当节点入栈时,栈的size可代表下一层节点的level。如果当前节点的level == size,则将peek.left = cur_node ,否则出栈元素,直到栈的size==level(由于后续字符串遍历到的节点为当前节点兄弟节点,或者当前节点祖辈的兄弟节点,所以 size>level),peek.right = cur_node。最后,当前节点也入栈,等待后续节点构建它的子树。
class Solution {
public TreeNode recoverFromPreorder(String S) {
//LinkedList 作为栈
Deque<TreeNode>deque = new LinkedList<>();
//level从0开始,代表第一层
int level = 0;
int pos = 0;
while(pos < S.length()){
if(S.charAt(pos) != -){
int []res = getNum(S,pos);
int val = res[0];
pos = res[1];
TreeNode node = new TreeNode(val);
//因为level从0开始,所以正好当level==size时,
//代表栈顶元素为当前节点的父节点
if(level == deque.size()){
if(!deque.isEmpty())
deque.peek().left = node;
}else{
//去除大于等于当前节点深度的栈中的节点
//类似先序的回溯过程
while(deque.size() > level){
deque.pop();
}
deque.peek().right = node;
}
deque.push(node);
level = 0;
}else{
level++;
pos++;
}
}
while(deque.size() > 1){
deque.pop();
}
return deque.peek();
}
int[] getNum(String s,int pos){
int end = pos;
while(end < s.length()&&s.charAt(end) != -){
end++;
}
return new int[]{
Integer.valueOf(s.substring(pos,end)),end};
}
}
下一篇:
让微信扫描直接下载你的APK
