代码随想录算法训练营第十八天|513.找树左下角的值 (迭代法实现)、112. 路径总和(递归法实现)、 106.从中序与后序遍历序列构造二叉树(一刷后来明白了)

文章介绍了三种二叉树问题的解法,包括使用迭代法找树左下角的值,递归法实现路径总和,以及根据中序与后序遍历序列构造二叉树。强调了迭代法在某些问题上的简洁性,以及在处理回溯问题时递归法的应用。同时,提供了关键代码和解题思路。

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

目录

513.找树左下角的值 (迭代法实现)

112. 路径总和(递归法实现)

106.从中序与后序遍历序列构造二叉树 (一刷后来明白了)


513.找树左下角的值 (迭代法实现)

本地递归偏难,反而迭代简单属于模板题, 两种方法掌握一下

题目链接/文章讲解/视频讲解:代码随想录

题解思路:

找左下角的值,本题用迭代法更好的理解,只需要记录最后一行的第一个元素的值即可,注意这里记录的方法,下面代码有注释和详解,然后踩过的坑就是之前把int size = dq.size();放到了循环外面,debug之后才发现不能这样的!!!

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int findBottomLeftValue(TreeNode root) {
        Deque<TreeNode> dq = new ArrayDeque<>();
        if(root != null) dq.offer(root);
        int result = 0;
        while(!dq.isEmpty()){
            int size = dq.size(); //这行代码不能放在while循环外面,如果放在外面则size会一直为1,当dq队列变化后需要跟着更新其size大小,因此需要不断的被执行,放在外面只会被执行一次
            for(int  i = 0; i < size; i++){
                TreeNode temp = dq.poll();
                if(i == 0) result = temp.val; //当i从0开始遍历的时候,说明是每一行的第一个元素,因此这里用来记录最后一行的第一个元素
                if(temp.left != null) dq.offer(temp.left);
                if(temp.right != null) dq.offer(temp.right);
            }
        }
        return result;
    }
}

112. 路径总和(递归法实现)

本题 又一次设计要回溯的过程,而且回溯的过程隐藏的还挺深,建议先看视频来理解

112. 路径总和,和 113. 路径总和ii 一起做了。 优先掌握递归法。

题目链接/文章讲解/视频讲解:代码随想录

题解思路:

本题注意卡哥视频里面的思路不能直接写在主函数里面,如果直接写在主函数里面则根节点的数没法进行先减,直接判断的就是根节点除外的到叶子节点的路径之和是否等于目标值了,所以需要先写另一个遍历的方法,然后在主函数里面直接引用该方法,此时就是传入目标值就是targetSUm - 根节点.val值了

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root == null) return false;
        return traverse(root, targetSum - root.val); //这里其实不能直接把traverse()方法里面的逻辑直接写到主函数里面,如果直接写在主函数里面则根节点的数没法进行先减,直接判断的就是根节点除外的到叶子节点的路径之和是否等于目标值了

    }

    public boolean traverse(TreeNode node, int count){
        if(node.left == null && node.right == null && count == 0) return true;
        if(node.left == null && node.right == null && count != 0) return false;
        if(node.left != null){
            count -= node.left.val;
            if(traverse(node.left, count)) return true; //如果左子树找到一条路径后,就直接返回true即可,不需要再往下进行判断了
            count += node.left.val;
        }

        if(node.right != null){
            count -= node.right.val;
            if(traverse(node.right, count)) return true; //如果右子树找到一条路径后,就直接返回true即可,不需要再往下进行判断了
            count += node.right.val;
        }

        return false;
    }
}

106.从中序与后序遍历序列构造二叉树 (一刷后来明白了)

本题算是比较难的二叉树题目了,大家先看视频来理解。

106.从中序与后序遍历序列构造二叉树,105.从前序与中序遍历序列构造二叉树 一起做,思路一样的

题目链接/文章讲解/视频讲解:代码随想录

题解思路:

先确定好左闭右闭的原则,这里优化的点在于用map保存中序序列的数值对应位置,方便根据后序数组中的数值查找中序数组中对应数值的索引位置,从而方便切割数组,因此每次递归不去构造新数组,根据下标索引值来指定范围内的数组去进行递归,比较省时间。然后AC这道题的关键在于一定要理清确定单词构造二叉树的逻辑递归的逻辑:1、先构建后序数组中最后一个元素的根节点,2、根据后序数组中的数值查找中序数组中对应数值的索引位置,开始切割数组,3、然后下面再去构建其左右节点,此时就是递归的操作了。OVER完毕!!!

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    Map<Integer,Integer> map = new HashMap<>();
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        for(int i = 0; i < inorder.length; i++){ //用map保存中序序列的数值对应位置,方便根据后序数组中的数值查找中序数组中对应数值的索引位置,从而方便切割数组
            map.put(inorder[i],i);
        }
        return buildTree(inorder, postorder, 0, inorder.length - 1, 0, postorder.length - 1);

    }

    //左闭右闭原则
    public TreeNode buildTree(int[] inorder, int[] postorder, int inBegin, int inEnd, int postBegin, int postEnd){ //每次递归不去构造新数组,根据下标索引值来指定范围内的数组去进行递归,比较省时间
    //第二步:确定终止条件
    if(inBegin > inEnd || postBegin > postEnd) return null;

    if(inBegin == inEnd || postBegin == postEnd) return new TreeNode(postorder[postBegin]); //后序数组中的最后一个元素为根节点元素。如果后序数组只有一个元素,则该二叉树就一个节点且节点val值就是该元素值,这一步可以省略,写这一步主要是为了减少一次递归!!!

    //第三步:确定单词构造二叉树的逻辑
    TreeNode node = new TreeNode(postorder[postEnd]); //先构建后序数组中最后一个元素的根节点,然后下面再去构建其左右节点,此时就是递归的操作了
    int rootIndex = map.get(postorder[postEnd]); //根据后序数组中的数值查找中序数组中对应数值的索引位置,开始切割数组
    node.left = buildTree(inorder, postorder, inBegin, rootIndex - 1, postBegin, postBegin + rootIndex -1 - inBegin);
    node.right = buildTree(inorder, postorder, rootIndex + 1, inEnd, postBegin + rootIndex - inBegin, postEnd - 1);
    return node;
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值