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

文章介绍了如何使用层次遍历和递归方法解决LeetCode中的四个问题,涉及树的左下角值查找、路径总和查找、以及基于中序和后/前序遍历构建二叉树。

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

LeetCode 513 找树左下角的值

在这里插入图片描述
本题思路:找到最底层最左边的值,我的想法是,利用层序遍历,分别存储每一层的值,然后取最后一层的第一个元素就是我们想得到值。

class Solution {
    public int findBottomLeftValue(TreeNode root) {
        List<List<Integer>> res = new ArrayList();
        Deque<TreeNode> queue = new ArrayDeque();
        queue.offer(root);
        while(!queue.isEmpty()){
            int size = queue.size();
            List<Integer> list = new ArrayList();
            while(size-- != 0){
                TreeNode cur = queue.poll();
                list.add(cur.val);
                if(cur.left!=null){
                queue.offer(cur.left);
                }
                if(cur.right!=null){
                queue.offer(cur.right);
                }
            }
            res.add(list);
        }
        return res.get(res.size()-1).get(0);        
    }
}


LeetCode 112 路径总和

在这里插入图片描述
本题思路: 利用递归来完成。 保存每一条路径的节点和。然后判断是否存在一个 sum 等于 targetSum,有的就添加到 res 中。

注意递归的时候,要回溯!

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root == null){
            return false;
        }
        List<Integer> paths = new ArrayList();
        List<Integer> res = new ArrayList();
        travel(root,paths,res,targetSum);
        if(res.size() > 0){
            return true;
        }
        return false;     
    }

 public void travel(TreeNode root, List<Integer> paths, List<Integer> res,int targetSum){
        // 先把根节点放入Paths中
        paths.add(root.val);
        if(root.left == null && root.right == null){
            int sum = 0;
            for(int i = 0; i < paths.size(); i++){
                sum += paths.get(i);
            }
            if(sum == targetSum){
                res.add(sum);
            }
            return;
        }
        if(root.left != null){
           travel(root.left,paths,res,targetSum);
           paths.remove(paths.size()-1); 
        }
        if(root.right != null){
           travel(root.right,paths,res,targetSum);
           paths.remove(paths.size()-1); 
        }
    }
}


LeetCode 113 路径总和||

在这里插入图片描述
本题思路: 和上一题一模一样,只不过我们再判断 sum == targetSum 之后,结果集存的是路径

注意:需要回溯

class Solution {
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        List<List<Integer>> res = new ArrayList();
        List<Integer> paths = new ArrayList();
        if(root == null){
            return res;
        }
        travel(root,paths,res,targetSum);
        return res;
    }

    public void travel(TreeNode root, List<Integer> paths, List<List<Integer>> res,int targetSum){
        paths.add(root.val);
        if(root.left == null && root.right == null){
            List<Integer> ans = new ArrayList();
            int sum = 0;
            for(int i = 0; i < paths.size(); i++){
                ans.add(paths.get(i));
                sum += paths.get(i);
            }
            // 路径和符合要求,才添加该路径
            if(sum == targetSum){
                res.add(ans);
            }
            return;
        }
        if(root.left != null){
            travel(root.left,paths,res,targetSum);
            paths.remove(paths.size()-1);
        }
        if(root.right != null){
            travel(root.right,paths,res,targetSum);
            paths.remove(paths.size()-1);
        }
    }
}

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

在这里插入图片描述
本题思路:利用后序遍历可以直到根节点的位置,而根据中序遍历,可以根据在后序遍历数组中的根节点位置,将中序数组分割成 左树和右树。

class Solution {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        // 如果 中序数组 长度为,直接返回空
        if(inorder.length == 0 || postorder.length == 0){
            return null;
        }
        return build(inorder,0,inorder.length,postorder,0,postorder.length);
    }
    public static TreeNode build(int[] inorder, int startInorder,int endInorder, int[] postorder,int startPostorder,int endPostorder){
        // 如果后序数组为空,说明遍历完,直接返回 null
        if(startPostorder == endPostorder){
            return null;
        }
        // 此处定义左闭右开
        int rootValue = postorder[endPostorder-1];
        TreeNode root = new TreeNode(rootValue);
        if(postorder.length == 1){
            return root;
        }
        int index;
        // 从中序数组中找节点下标
        for(index = startInorder; index < inorder.length; index++){
            if(inorder[index] == rootValue){
                break;
            }
        }
        int leftstartInorder = startInorder;
        int leftendInorder = index;
        int rightstartInorder = index+1;
        int rightendInoreder = endInorder;

        int leftstartpostorder = startPostorder ;
        int leftendpostorder = startPostorder + (index - startInorder);
        int rightstartpostorder = leftendpostorder;
        int rightendpostorder = endPostorder-1;
        
        root.left = build(inorder,leftstartInorder,leftendInorder,postorder,leftstartpostorder,leftendpostorder);
        root.right = build(inorder,rightstartInorder,rightstartInorder,postorder,rightstartpostorder,rightendpostorder);
        return root;
    }
}

注意: 在进行数组分割的时候,因为只有分割中序数组之后,才知道左右子树的元素个数,才能分割后序数组

  1. 先分割中序数组
  2. 再分割后序数组

LeetCode 105 从前序与后序遍历构造二叉树

在这里插入图片描述
本题思路: 和上题思路一样,只不过分割数组的时候不太一样

注意:

  1. 先分割中序数组
  2. 再分割前序数组
class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if(preorder.length == 0 || inorder.length == 0){
            return null;
        }
        return build(inorder,0,inorder.length,preorder,0,preorder.length);
    }

    public TreeNode build(int[] inorder, int startInorder,int endInorder, int[] preorder, int startPreorder,int endPreorder){
        // 找到出口
        if(startPreorder == endPreorder){
            return null;
        }
        int rootValue = preorder[startPreorder];
        TreeNode root = new TreeNode(rootValue);
        if(preorder.length == 1){
            return root;
        }
        int index = 0;
        for(index = startInorder; index < inorder.length; index++){
            if(inorder[index] == rootValue){
                break;
            }
        }
        // 分割中序数组
        int leftstartinorder = startInorder;
        int leftendinorder = index;
        int rightstartinorder = index+1;
        int rightendinorder = endInorder;

        // 分割前序数组
        int leftstartpreorder = startPreorder+1;
        int leftendpreorder = leftstartpreorder + (index - startInorder);
        int rightstartpreorder = leftendpreorder;
        int rightendpreorder = endPreorder;
        root.left = build(inorder,leftstartinorder,leftendinorder,preorder,leftstartpreorder,leftendpreorder);
        root.right = build(inorder,rightstartinorder,rightendinorder,preorder,rightstartpreorder,rightendpreorder);
        return root;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个想打拳的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值