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

本文介绍了如何在二叉树中找左下角的值,路径总和以及如何根据中序和后序遍历序列构造二叉树。通过迭代和递归法解决找左下角值问题,路径总和的判断条件,以及中序后序遍历序列构造二叉树的思路。强调了遍历顺序和回溯的重要性,并给出了相关题目的解题思路和代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


513.找左下角的值

迭代法较简单理解,递归法较难理解!

思路

迭代法思路:按照层序遍历为模板,然后对每层遍历到的第一个节点做逻辑处理就完成了。

递归法思路:要找最左下角的节点,这里要满足两个条件:1.最深 2.左下角;
只要保证遍历顺序是左优先就可以获得左的节点,所以使用中序或者后序遍历都可以;
然后是“最”该如何获得呢?这个其实是深度最深的意思,所以一直递归获得深度最深的;所以在中的处理逻辑是—第一层判断:当前节点的左右节点为空,此判断获得所有最左边的节点;第二层判断:判断maxdeep是否大于每次迭代获得的deep,若小于就重新给maxdeep赋值当前最深的deep,满足要求的value1就是当前节点的值。

注意

初始化maxdeep要注意等于多少,因为不排除深度为0的情况,所以它不能为0,因此赋值保证小于0就好。

实现代码

递归法:

//找最左下角,遍历顺序是左优先的
 //要找满足深度最深的
class Solution {
    int value=0;
    int maxdeep=-1;
    public int findBottomLeftValue(TreeNode root) {
        getDeep(root,0);
        return value;    
    }
    public void getDeep(TreeNode root,int deep){
        if(root==null){
            return;
        }
        //左
        getDeep(root.left,deep+1);

        //中
        if(root.left==null&&root.right==null){
            if(deep>maxdeep){
                maxdeep=deep;
                value=root.val;
            }
        }

        //右
        getDeep(root.right,deep+1);
    }
}

112.路径总和

是否需要返回值辨析

对于一个方法是否需要有返回值的问题,就以树来说:

1.若需要将整棵树都遍历一遍才能得出最后结果的,那么不需要返回值;
2.若是当一遇到满足条件就马上返回的情况,也就是不一定需要遍历完整棵树就可以得出结果的,就需要返回值。

思路

题目要求需要从根节点出发一直到叶子节点,整条路径的节点值相加等于给出的目标值,说明存在这样的路径的话就返回true。这里可以采用任一种遍历方式;对中的处理是:首先是当前节点的左右子树都为空,然后第二层判断条件是targetSum的值为0,这里就要说明一下:每遍历一个节点就用当前的targetSum-当前节点值,最后若为0说明符合条件马上返回true;之后就是当前节点的左右节点的递归了。

注意

要判断一条路径的总节点值是否与目标值相等,第一想法就是先相加然后再和目标值匹配,这个方法有点复杂;
所以可以用目标值减去每个遍历节点的值,看最后是否等于0就可以判断是否相等了,很多情况都可以用到,一定要记得这个思路!!!

实现代码

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        return getTarget(root,targetSum); 
    }
    public boolean getTarget(TreeNode root,int targetSum){
        if(root==null){
            return false;
        }
        targetSum-=root.val;

        if(root.left==null&&root.right==null){
            if(targetSum==0){
                return true;
            }
        }

        boolean left=hasPathSum(root.left,targetSum);
        if(left){
            return true;
        }

        boolean right=hasPathSum(root.right,targetSum);
        if(right){
            return true;
        }
        return false;
    }
}

相关题目

113.路径总和2

思路

此题目是在112.路径总和后的相关题目,这个需要将所有满足要求的路径找到,所以不设置返回值;然后要将满足要求的节点放入一个小集合,最后再将所以小集合放入到大集合中;这里要注意要回溯,如果这条路径满足要求,或者不满足要求,那都需要回溯去找其他路径。

注意

在将小集合加入大集合中时,每次都需要新建小集合list,这个可以这样理解:就是小集合是用来存放一条满足要求的路径,那么有不同的路径就需要集合存的内容不一样,所以每一条路径的开头都要new ArrayList<>(list)表示新建。

实现代码

 public void getAll(TreeNode root,int targetSum,List<Integer> list,List<List<Integer>> res){
        //要获得所有符合要求的路径,一定要记得在递归后进行回溯
        if(root==null){
            return;
        }
        list.add(root.val);
        targetSum-=root.val;
        if(root.left==null&&root.right==null){
            if(targetSum==0){
        //因为list是引用传递,为了防止递归的时候分支污染,我们要在每个路径中都要新建一个list
                res.add(new ArrayList<>(list));
            }
            return;
        }

        if(root.left!=null){
            getAll(root.left,targetSum,list,res);//递归
            list.remove(list.size()-1);//回溯
        }

        if(root.right!=null){
            getAll(root.right,targetSum,list,res);
            list.remove(list.size()-1);
        }
    }
}

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

这道题我理解也可以按照步骤写出代码,但是一直出现错误,不知道为什么!!!

思路

后序遍历是:左右中,说明在后序数组中最后一个数是根节点数;
用map存储前序数组里面的数,然后定位到根节点数的位置,在这个位置的左边是左子树,右边是右子树,以此根节点为分割点;然后统计左子树的长度用来切割后序数组;
因为后序数组的最后一个数是根节点所以一定要记得将这个数减去,在切割后序遍历的右子树范围要将这个排除。

实现代码

class Solution {
    Map<Integer, Integer> map;  // 方便根据数值查找位置
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        map = new HashMap<>();
        for (int i = 0; i < inorder.length; i++) { // 用map保存中序序列的数值对应位置
            map.put(inorder[i], i);
        }

        return findNode(inorder,  0, inorder.length, postorder,0, postorder.length);  // 前闭后开
    }
    
    public TreeNode findNode(int[] inorder, int inBegin, int inEnd, int[] postorder, int postBegin, int postEnd) {
        // 参数里的范围都是前闭后开
        if (inBegin >= inEnd || postBegin >= postEnd) {  // 不满足左闭右开,说明没有元素,返回空树
            return null;
        }
        int rootIndex = map.get(postorder[postEnd - 1]);  // 找到后序遍历的最后一个元素在中序遍历中的位置
        TreeNode root = new TreeNode(inorder[rootIndex]);  // 构造结点
        int lenOfLeft = rootIndex - inBegin;  // 保存中序左子树个数,用来确定后序数列的个数
        root.left = findNode(inorder, inBegin, rootIndex,
                            postorder, postBegin, postBegin + lenOfLeft);
        root.right = findNode(inorder, rootIndex + 1, inEnd,
                            postorder, postBegin + lenOfLeft, postEnd - 1);

        return root;
    }
}

相关题目

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


总结

这三道题都要加强理解,特别是按照遍历得出序列来构造二叉树,里面的一些逻辑还有点不清晰。
二刷的重点关注对象,并且要把里面的知识点要提取出来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值