空间代价替代时间代价-LeetCode105-从前序与中序遍历序列构造二叉树

题目

根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
    3
   / \
  9  20
    /  \
   15   7

思路

先序遍历的第一个元素即为树的根节点。中序遍历被这个根节点分为两部分,左边部分在根节点左边,右边部分在根节点右边。分别在左边部分和右边部分找到它们的根结点(在先序遍历中位置最前的那个元素即为根节点)。如此递归下去。递归参数:根节点,被根结点拆分的数组。递归方法:根据根节点将数组拆分,并分别找出拆分部分的根节点,再递归。

代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public static  Map<Integer,Integer> map;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if(preorder.length==0){
            return null;
        }
        //将前序中的值与位置存储到map中,用空间代价减少时间代价,减少了一个for循环的复杂度
        map = new HashMap<Integer, Integer>();
        for(int i=0;i<preorder.length;i++){
            map.put(preorder[i], position_of_order(preorder,preorder[i]));
        }
        
        TreeNode rootnode=new TreeNode(preorder[0]);
        digui(rootnode,inorder,preorder);
        return rootnode;
    }
    public void digui(TreeNode zhongfennode,int[] inorder,int[] preorder){
        if(inorder.length==1){
            return;
        }

        int position=position_of_order(inorder,zhongfennode.val);
        
        //zhongfennode在最左边
        if(position==0){
            int[] right=new int[inorder.length-position-1];
            int rightnodeindex=-1;
            for(int i=0;i<inorder.length-position-1;i++){
                right[i]=inorder[i+position+1];
                if(rightnodeindex==-1){
                    //rightnodeindex=position_of_order(preorder,right[i]); 
                    //上面换成下面,减少了一个for循环的复杂度
                    rightnodeindex=map.get(right[i]);
                }else{
                    // if(position_of_order(preorder,right[i])<rightnodeindex){
                    //     rightnodeindex=position_of_order(preorder,right[i]);
                    // }
                    //上面换成下面,减少了一个for循环的复杂度
                    if(map.get(right[i])<rightnodeindex){
                        rightnodeindex=map.get(right[i]);
                    }
                }  
            }
            TreeNode rightnode=new TreeNode(preorder[rightnodeindex]);
            zhongfennode.right=rightnode;
            digui(rightnode,right,preorder); 
        }else if(position==inorder.length-1){
            //zhongfennode在最右边
            int[] left=new int[position];
            int leftnodeindex=-1;
            for(int i=0;i<position;i++){
                left[i]=inorder[i];
                if(leftnodeindex==-1){
                    //leftnodeindex=position_of_order(preorder,left[i]);
                    //上面换成下面,减少了一个for循环的复杂度
                    leftnodeindex=map.get(left[i]); 
                }else{
                    // if(position_of_order(preorder,left[i])<leftnodeindex){
                    //     leftnodeindex=position_of_order(preorder,left[i]);
                    // }
                    //上面换成下面,减少了一个for循环的复杂度
                     if(map.get(left[i]) <leftnodeindex){
                        leftnodeindex=map.get(left[i]); ;
                    }  
                }
            }
            TreeNode leftnode=new TreeNode(preorder[leftnodeindex]);
            zhongfennode.left=leftnode;
            digui(leftnode,left,preorder);
        }else{
            //zhongfennode在中间某位置
            int[] left=new int[position];
            int leftnodeindex=-1;
            int[] right=new int[inorder.length-position-1];
            int rightnodeindex=-1;
        
            for(int i=0;i<position;i++){
                left[i]=inorder[i];
                if(leftnodeindex==-1){
                    //leftnodeindex=position_of_order(preorder,left[i]);
                    //上面换成下面,减少了一个for循环的复杂度
                    leftnodeindex=map.get(left[i]); 
                }else{
                    // if(position_of_order(preorder,left[i])<leftnodeindex){
                    //     leftnodeindex=position_of_order(preorder,left[i]);
                    // }
                    //上面换成下面,减少了一个for循环的复杂度
                    if(map.get(left[i]) <leftnodeindex){
                        leftnodeindex=map.get(left[i]); ;
                    }
                }
            }
            for(int i=0;i<inorder.length-position-1;i++){
                right[i]=inorder[i+position+1];
                if(rightnodeindex==-1){
                    //rightnodeindex=position_of_order(preorder,right[i]);
                    //上面换成下面,减少了一个for循环的复杂度
                    rightnodeindex=map.get(right[i]); 
                }else{
                    // if(position_of_order(preorder,right[i])<rightnodeindex){
                    //     rightnodeindex=position_of_order(preorder,right[i]);
                    // }
                    //上面换成下面,减少了一个for循环的复杂度                      
                    if(map.get(right[i])<rightnodeindex){
                        rightnodeindex=map.get(right[i]);
                    }
                }
           }
                       
           TreeNode leftnode=new TreeNode(preorder[leftnodeindex]);
           zhongfennode.left=leftnode;
           digui(leftnode,left,preorder); 
                     
           TreeNode rightnode=new TreeNode(preorder[rightnodeindex]);
           zhongfennode.right=rightnode;
           digui(rightnode,right,preorder); 
        }  
        
    }
    public int position_of_order(int[] order,int val){
        for(int i=0;i<order.length;i++){
            if(order[i]==val){
                return i;
            }
        }
        return 0;
    }
}

注意

第一次写的代码为注释掉的代码,超时。为了解决超时的问题,引入map类型,将for循环得到的值存到map中,用空间代价减少时间代价。

思路2

外层循环遍历先序数组,第一个元素为根节点。第二元素与第一个元素在中序数组的位置进行比较,判断位置在根结点的左还是右。第三个元素与第一个元素在中序数组的位置进行比较,假如在左,判断第一个元素左侧是否为空,若为空则将第三个元素放在此处,若不为空,第三个元素再次与第一个元素左侧这个元素进行第二轮比较。。。以此类推。

class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if(preorder.length==0){
            return null;
        }
        TreeNode[] treenodes=new TreeNode[preorder.length];
        for(int i=0;i<preorder.length;i++){
            treenodes[i]=new TreeNode(preorder[i]);
        }

        for(int i=1;i<preorder.length;i++){
            for(int j=0;j<i;j++){
                if(position_of_order(inorder,preorder[i])<position_of_order(inorder,preorder[j])){
                    if(treenodes[j].left==null){
                       treenodes[j].left=treenodes[i];
                        break;
                    }else{
                       j=position_of_order(preorder,treenodes[j].left.val)-1;
                    }
                }else{
                    if(treenodes[j].right==null){
                       treenodes[j].right=treenodes[i];
                        break;
                    }else{
                       j=position_of_order(preorder,treenodes[j].right.val)-1;
                    }
                }
            }
            
            
        }
        return treenodes[0];
    }
    
    public int position_of_order(int[] order,int val){
        for(int i=0;i<order.length;i++){
            if(order[i]==val){
                return i;
            }
        }
        return 0;
    }
}

注意

超时,可利用map类型,减少一个for循环,用空间代价减少时间代价。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值