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};
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42007742/article/details/106827485