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

513.找树左下角的值  

使用层序遍历,该题则是遍历到最后一层时第一个存入的值便为树左下角的值

这是自己思考后写出的代码:

class Solution {
    public int findBottomLeftValue(TreeNode root) {
        if (root.left == null && root.right == null)
            return root.val;
        Queue<TreeNode> q = new LinkedList<>();
        q.offer(root);

        int res = 0;
        while (!q.isEmpty()) {
            int sz = q.size();

            for (int i = 0; i < sz; i++) {
                TreeNode cur = q.poll();

                if (cur.left != null) {
                    q.offer(cur.left);
                }
                if (cur.right != null) {
                    q.offer(cur.right);
                }
            }
            // 此时记录下一层第一个元素
            TreeNode nxt = q.peek();
            // 如果为空则说明为最后一层
            if (nxt == null) {
                break;
            }
            if (nxt.left == null && nxt.right == null) {
                res = nxt.val;
            }
        }
        return res;
    }
}

而如若使用【递归】解决

由于二叉树递归遍历是先遍历左子树,再遍历右子树,所以到最大深度时第一次遇见的节点便是树的左下角的节点

代码如下:

class Solution {
    // 记录二叉树的最大深度
    int maxDepth = 0;
    // 记录 traverse 递归遍历到的深度
    int depth = 0;
    TreeNode res = null;

    public int findBottomLeftValue(TreeNode root) {
        traverse(root);
        return res.val;
    }

    void traverse(TreeNode root) {
        if (root == null) {
            return;
        }
        // 前序遍历位置
        depth++;
        if (depth > maxDepth) {
            // 到最大深度时第一次遇到的节点就是左下角的节点
            maxDepth = depth;
            res = root;
        }
        if(root.left != null){
            traverse(root.left);
        }
        if(root.right != null){
            traverse(root.right);
        }
        // 后序遍历位置
        depth--;
    }
}

112.路径总和

这道题很简单,无非就是遍历二叉树的时候将路径值进行相加,进行判断

代码如下:

class Solution {
    /* 解法一、分解问题的思路 */
    // 定义:输入一个根节点,返回该根节点到叶子节点是否存在一条和为 targetSum 的路径
    public boolean hasPathSum(TreeNode root, int targetSum) {
        // base case
        if (root == null) {
            return false;
        }
        if (root.left == root.right && root.val == targetSum) {
            return true;
        }

        return hasPathSum(root.left, targetSum - root.val)
                || hasPathSum(root.right, targetSum - root.val);
    }

    /* 解法二、遍历二叉树的思路 */
    int target;
    boolean found = false;
    // 记录遍历过程中的路径和
    int curSum = 0;

    public boolean hasPathSum_2(TreeNode root, int targetSum) {
        if (root == null) {
            return false;
        }
        this.target = targetSum;
        traverse(root);
        return found;
    }

    // 二叉树遍历函数
    void traverse(TreeNode root) {
        if (root == null) {
            return;
        }
        // 前序遍历位置
        curSum += root.val;
        if (root.left == null && root.right == null) {
            if (curSum == target) {
                found = true;
            }
        }

        traverse(root.left);
        traverse(root.right);

        // 后序遍历位置
        curSum -= root.val;
    }
}

113.路径总和II

该题目在112的基础上改变了返回值,该题目需要返回的是路径,则将符合题解的路径存入即可

代码如下:

class Solution {
    int sum = 0;
    List<List<Integer>> res = new LinkedList<>();
    LinkedList<Integer> track = new LinkedList<>();
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
       if(root == null) return res;

       backtrack(root,targetSum);
       return res;
    }

    public void backtrack(TreeNode root,int targetSum) {
        if(root == null) return;

        sum += root.val;
        track.add(root.val);
        if(root.left == null && root.right == null){
            if(sum == targetSum){
                res.add(new LinkedList<>(track));
            }
        }
        backtrack(root.left,targetSum);
        backtrack(root.right,targetSum);
        track.removeLast();    
        sum -= root.val;
    }
}

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

首先明确前序遍历 与 中序遍历的数组元素分布特点

 

找到根节点是很简单的,前序遍历的第一个值 preorder[0] 就是根节点的值。

关键在于如何通过根节点的值,将 preorder 和 inorder 数组划分成两半,构造根节点的左右子树?

所以就需要利用中序遍历确定二叉树的左右子树部分

对于  preorder数组情况

 所以代码如下:

class Solution {
    // 存储 inorder 中值到索引的映射
    HashMap<Integer,Integer> valToIndex = new HashMap<>();

    public TreeNode buildTree(int[] preorder, int[] inorder) {
        for(int i = 0;i < inorder.length; i++){
            valToIndex.put(inorder[i], i);
        }
        return build(preorder,0,preorder.length - 1,
                    inorder,0,inorder.length - 1);
    }

    public TreeNode build(int[] preorder, int preStart, int preEnd,
                          int[] inorder, int inStart, int inEnd){
        // 判断给出的先序遍历结果是否合理
        if(preStart > preEnd){
            return null;
        }

        // root 节点对应的值就是前序遍历数组的第一个元素
        int rootVal = preorder[preStart];
        // rootVal 在中序遍历数组中的索引
        int index = valToIndex.get(rootVal);

        int leftSize = index - inStart;

        // 先构造出当前根节点
        TreeNode root = new TreeNode(rootVal);
        // 递归构造左右子树
        root.left = build(preorder,preStart + 1,preStart + leftSize,
                inorder,inStart,index - 1);
        root.right = build(preorder,preStart + leftSize + 1,preEnd,
                inorder,index + 1,inEnd);
        return root;
    }
}

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

思路与105一致

数组索引变为:

 

代码如下:

class Solution {
    // 存储 inorder 中值到索引的映射
    HashMap<Integer, Integer> valToIndex = new HashMap<>();

    public TreeNode buildTree(int[] inorder, int[] postorder) {
        for (int i = 0; i < inorder.length; i++) {
            valToIndex.put(inorder[i], i);
        }
        return build(inorder, 0, inorder.length - 1,
                    postorder, 0, postorder.length - 1);
    }

    /*
       定义:
       中序遍历数组为 inorder[inStart..inEnd],
       后序遍历数组为 postorder[postStart..postEnd],
       构造这个二叉树并返回该二叉树的根节点
    */
    TreeNode build(int[] inorder, int inStart, int inEnd,
                int[] postorder, int postStart, int postEnd) {

        if (inStart > inEnd) {
            return null;
        }
        // root 节点对应的值就是后序遍历数组的最后一个元素
        int rootVal = postorder[postEnd];
        // rootVal 在中序遍历数组中的索引
        int index = valToIndex.get(rootVal);
        // 左子树的节点个数
        int leftSize = index - inStart;
        TreeNode root = new TreeNode(rootVal);
        // 递归构造左右子树
        root.left = build(inorder, inStart, index - 1,
                         postorder, postStart, postStart + leftSize - 1);
        
        root.right = build(inorder, index + 1, inEnd,
                          postorder, postStart + leftSize, postEnd - 1);
        return root;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值