代码随想录算法训练营第十八天|513.找树左下角的值、112.路径总和、113.路径总和II、106.从中序与后序遍历构造二叉树、105.从前序与中序遍历构造二叉树

代码随想录算法训练营第十八天|513.找树左下角的值、112.路径总和、113.路径总和II、106.从中序与后序遍历构造二叉树、105.从前序与中序遍历构造二叉树

513.找树左下角的值

给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。

假设二叉树中至少有一个节点。

示例 1:

img

输入: root = [2,1,3]
输出: 1

题解:看清楚题目!!是树的最后一行最左边的节点,不是树的最左的左节点,也就是说这个节点可以是右节点

代码

递归解法:如果节点是叶子节点,判断当前深度是不是最大深度,是的话就保存该节点的值,然后更新深度,不是则不更新值和深度。

class Solution {
    int deeps=-1;
    int value=0;
    public int findBottomLeftValue(TreeNode root) {
        if(root==null) return 0;
        digui(root,0);
        return value;
    }
    public void digui(TreeNode node,int deep){
       if(node==null) return ;
       if(node.left==null && node.right==null){
            if(deep>deeps){
                value=node.val;
                deeps=deep;
            }
       }
       digui(node.left,deep+1);
       digui(node.right,deep+1);
    }
}

迭代解法:层序遍历,最后一个节点的值就是需要的值。

class Solution {
    public int findBottomLeftValue(TreeNode root) {
        if(root==null) return 0;
        Queue<TreeNode> que=new LinkedList<>();
        que.offer(root);
        int res=0;
        while(!que.isEmpty()){
            int len=que.size();
            for(int i=0;i<len;i++){
                TreeNode node=que.poll();
                if(i==0) res=node.val;
                if(node.left!=null) que.offer(node.left);
                if(node.right!=null) que.offer(node.right);
            }
        }
        return res;
    }
}

112.路径总和

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false

叶子节点 是指没有子节点的节点。

示例 1:

img

输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。

题解:递归解决这个题。从跟节点开始,每到要遍历到下一个节点,要减去当前节点的值,减到最后一个节点,如果目标值减去的值和叶子节点的值相等,说明这是一条可行的道路。需要注意的是,最后的判断条件,target不是等于0,而是看是否等于最后一个叶子节点

代码

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root==null) return false;
        if(root.left==null && root.right==null && targetSum==root.val){
            return true;
        }
        if(root.left!=null){
           boolean flag=hasPathSum(root.left,targetSum-root.val);
           if(flag) return true;
        }
        if(root.right!=null){
            boolean flag=hasPathSum(root.right,targetSum-root.val);
            if(flag) return true;
        }
        return false;
    }
}

113.路径总和II

给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。

叶子节点 是指没有子节点的节点。

示例 1:

img

输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:[[5,4,11,2],[5,8,4,5]]

题解:该怎么保存经过的路径呢?用LIst保存经过的节点的值,然后再将list添加到LIst<List>中。需要注意的是,在添加到最后的结果数组时,添加的需要时list的备份,不然会改变list里面的值,影响下一条路径节点值的保存

//不是很好的方法,new ArrayList<>(list)相当于给每个节点都新建了一个对象,但是代码便于理解。

代码

class Solution {
    List<List<Integer>> res=new ArrayList<>();
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        List<Integer> list=new ArrayList<>();
        digui(root,targetSum,list);
        return res;
    }
    public void digui(TreeNode node,int targetSum,List<Integer> list){
        if(node==null) return;
        list.add(node.val);
        //满足条件,加入路径
        if(node.left==null && node.right==null && node.val==targetSum){
            res.add(new ArrayList<>(list));
        }
        if(node.left!=null){
            digui(node.left,targetSum-node.val,new ArrayList<>(list));
        }
        if(node.right!=null){
            digui(node.right,targetSum-node.val,new ArrayList<>(list));
        }
    }
}

106.从中序与后序遍历构造二叉树

给定两个整数数组 inorderpostorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树

示例 1:

img

输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
输出:[3,9,20,null,null,15,7]

题解:后序和中序构造二叉树的步骤:

  • 后序数组为空,空节点
  • 后序数组的最后一个元素是根节点
  • 寻找中序数组位置的切割点
  • 切中序数组
  • 切后序数组
  • 递归处理左区间后区间

代码

class Solution {
    Map<Integer,Integer> map=new HashMap<>();
    public TreeNode buildTree(int[] in, int[] po) {
        for(int i=0;i<in.length;i++){    //保存前序的节点,便于分割
            map.put(in[i],i); 
        }
        return getNode(in,0,in.length,po,0,po.length);
    }
    //递归实现分割过程
    public TreeNode getNode(int[] in,int inbegin,int inend,int [] po,int pobegin,int poend){
        if(inbegin>=inend || pobegin>=poend) return null;
        //这里需要注意,中间节点的改变
        int rootIndex=map.get(po[poend-1]);
        TreeNode root=new TreeNode(in[rootIndex]);
        int llen=rootIndex-inbegin;
        root.left=getNode(in,inbegin,rootIndex,po,pobegin,pobegin+llen);
        root.right=getNode(in,rootIndex+1,inend,po,pobegin+llen,poend-1);
        return root;
    }
}

105.从前序与中序遍历构造二叉树

给定两个整数数组 preorderinorder ,其中 preorder 是二叉树的先序遍历inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

示例 1:

img

输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]

题解:和上一个题相比,有一个问题:pre的开始节点要怎么确定呢,第一个当然是0,第二个是加上len后的位置,但是len 又得在开始节点后面才能确定,所以要怎么解决这个问题呢?方法很简单,在传入参数的时候,参数加一就可以了。

代码

class Solution {
    Map<Integer,Integer> map=new HashMap<>();
    public TreeNode buildTree(int[] pre, int[] in) {
        //把中序数组放进map
        for(int i=0;i<in.length;i++){
            map.put(in[i],i);
        }
        return getNode(pre,0,pre.length,in,0,in.length);
    }
    public TreeNode getNode(int [] pre,int preb,int pree,int[] in,int inb,int ine){
        if(inb>=ine || preb>=pree) return null;
        int rootIndex=map.get(pre[preb]);
        TreeNode root=new TreeNode(in[rootIndex]);
        int llen=rootIndex-inb;
        root.left=getNode(pre,preb+1,preb+llen+1,in,inb,rootIndex);
        root.right=getNode(pre,preb+llen+1,pree,in,rootIndex+1,ine);
        return root;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值