LeetCode刷题Day15——二叉树(树左下角的值、路径和、树的构造、最大二叉树、合并二叉树)

简介: 一、找树左下角的值题目链接:513. 找树左下角的值

一、找树左下角的值

题目链接:513. 找树左下角的值

/**
 * <pre>
 * 1.广搜,每一层遍历,找到最左边的节点记录下值
 * 2.深搜,找到最深的一层就将结果记录下来,先遍历的是左节点,所以右节点如果同样高度则不会覆盖掉左节点的值,保证了最终找到的是最左边的节点
 * </pre>
 *
 * @author <a href="https://github.com/Ken-Chy129">Ken-Chy129</a>
 * @date 2023/1/16 13:44
 */
public class 找树左下角的值513 {
    public int findBottomLeftValue(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        int ans = root.val;
        boolean flag = true; // 此处也可以不使用flag,而是每次offer入队的时候先入right节点,那么最后一次poll出来的节点就是当层最左边的节点
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i=0; i<size; i++) {
                TreeNode poll = queue.poll();
                if (poll.left != null) {
                    queue.offer(poll.left);
                    if (flag) {
                        ans = poll.left.val;
                        flag = false;
                    }
                }
                if (poll.right != null) {
                    queue.offer(poll.right);
                    if (flag) {
                        ans = poll.right.val;
                        flag = false;
                    }
                }
            }
            flag = true;
        }
        return ans;
    }
    int res = 0;
    int maxHeight = -1;
    public int findBottomLeftValue2(TreeNode root) {
        dfs(root, 0);
        return res;
    }
    public void dfs(TreeNode root, int height) {
        if (root.left == null && root.right == null) {
            if (height > maxHeight) {
                maxHeight = height;
                res = root.val;
            }
            return;
        }
        if (root.left != null) {
            dfs(root.left, height+1);
        }
        if (root.right != null) {
            dfs(root.right, height+1);
        }
    }
}

二、路径总和

题目链接:112. 路径总和

/**
 * <pre>
 * 1.深搜
 * 2.广搜
 * 节点的值有可能是负数,所以不能大于targetSum就剪枝
 * </pre>
 *
 * @author <a href="https://github.com/Ken-Chy129">Ken-Chy129</a>
 * @date 2023/1/16 15:19
 */
public class 路径总和112 {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if (root == null) {
            return false;
        }
        return dfs(root, targetSum, root.val);
    }
    public boolean dfs(TreeNode root, int targetSum, int nowSum) {
        if (root.left == null && root.right == null) {
            return nowSum == targetSum;
        }
        boolean rs1=false, rs2=false;
        if (root.left != null) {
            rs1 = dfs(root.left, targetSum, nowSum+root.left.val);
        }
        if (root.right != null) {
            rs2 = dfs(root.right, targetSum, nowSum+root.right.val);
        }
        return rs1 || rs2;
    }
    public boolean hasPathSum2(TreeNode root, int targetSum) {
        if (root == null) {
            return false;
        }
        Queue<TreeNode> nodeQueue = new LinkedList<>();
        Queue<Integer> sumQueue = new LinkedList<>();
        nodeQueue.offer(root);
        sumQueue.offer(root.val);
        while (!nodeQueue.isEmpty()) {
            int size = nodeQueue.size();
            for (int i=0; i<size; i++) {
                TreeNode node = nodeQueue.poll();
                Integer sum = sumQueue.poll();
                if (node.left == null && node.right == null) {
                    if (sum == targetSum) {
                        return true;
                    }
                }
                if (node.left != null) {
                    nodeQueue.offer(node.left);
                    sumQueue.offer(sum+node.left.val);
                }
                if (node.right != null) {
                    nodeQueue.offer(node.right);
                    sumQueue.offer(sum+node.right.val);
                }
            }
        }
        return false;
    }
}

三、从前序与中序遍历序列构造二叉树

题目链接:105. 从前序与中序遍历序列构造二叉树

/**
 * <pre>
 * 递归:从前往后依次取出前缀遍历数组的值,以其作为分割点,不断将中序数组分割为左右子树
 * </pre>
 *
 * @author <a href="https://github.com/Ken-Chy129">Ken-Chy129</a>
 * @date 2023/1/16 17:24
 */
public class 从前序与中序遍历序列构造二叉树105 {
    int pre_idx = 0;
    int[] preorder;
    int[] inorder;
    Map<Integer, Integer> idx_map = new HashMap<>();
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        this.preorder = preorder;
        this.inorder = inorder;
        int index = 0;
        for (int val : inorder) {
            idx_map.put(val, index++);
        }
        return build(0, inorder.length-1);
    }
    public TreeNode build(int in_left, int in_right) {
        if (in_left > in_right) {
            return null;
        }
        int val = preorder[pre_idx++];
        TreeNode root = new TreeNode(val);
        Integer index = idx_map.get(val);
        root.left = build(in_left, index-1);
        root.right = build(index+1, in_right);
        return root;
    }
}

四、从中序与后序遍历序列构造二叉树

题目链接:106.从中序与后序遍历序列构造二叉树

/**
 * <pre>
 * 递归:从后往前依次取出前缀遍历数组的值,以其作为分割点,不断将中序数组分割为右左子树
 * </pre>
 *
 * @author <a href="https://github.com/Ken-Chy129">Ken-Chy129</a>
 * @date 2023/1/16 16:21
 */
public class 从中序与后序遍历序列构造二叉树106 {
    int post_idx;
    int[] postorder;
    int[] inorder;
    Map<Integer, Integer> idx_map = new HashMap<>();
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        this.inorder = inorder;
        this.postorder = postorder;
        post_idx = postorder.length - 1;
        int index = 0;
        for (int val : inorder) {
            idx_map.put(val, index++);
        }
        return build(0, inorder.length-1);
    }
    public TreeNode build(int in_left, int in_right) {
        // 如果这里没有节点构造二叉树了,就结束
        if (in_left > in_right) {
            return null;
        }
        // 选择 post_idx 位置的元素作为当前子树根节点
        int root_val = postorder[post_idx];
        TreeNode root = new TreeNode(root_val);
        // 根据 root 所在位置分成左右两棵子树
        int index = idx_map.get(root_val);
        // 下标减一
        post_idx--;
        // 先构造右子树,因为从后取后序遍历数组的值,去完根节点后接着最开始取到的就是最右边的节点
        root.right = build(index + 1, in_right);
        // 构造左子树
        root.left = build(in_left, index - 1);
        return root;
    }
}

五、最大二叉树

题目链接:654. 最大二叉树

/**
 * <pre>
 * 递归
 * 单调栈
 * </pre>
 *
 * @author <a href="https://github.com/Ken-Chy129">Ken-Chy129</a>
 * @date 2023/1/17 11:45
 */
public class 最大二叉树654 {
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        if (nums.length == 0) {
            return null;
        }
        TreeNode root = new TreeNode();
        int max = nums[0], index=0;
        for (int i=1; i<nums.length; i++) {
            if (nums[i] > max) {
                index = i;
                max = nums[i];
            }
        }
        root.val = max;
        root.left = constructMaximumBinaryTree(Arrays.copyOfRange(nums, 0, index));
        root.right = constructMaximumBinaryTree(Arrays.copyOfRange(nums, index+1, nums.length));
        return root;
    }
}

六、合并二叉树

题目链接:617. 合并二叉树

/**
 * <pre>
 * 1.深搜
 * 2.广搜
 * </pre>
 *
 * @author <a href="https://github.com/Ken-Chy129">Ken-Chy129</a>
 * @date 2023/1/17 12:23
 */
public class 合并二叉树617 {
    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        if (root1 == null) {
            return root2;
        }
        if (root2 == null) {
            return root1;
        }
        TreeNode merged = new TreeNode(root1.val + root2.val);
        merged.left = mergeTrees(root1.left, root2.left);
        merged.right = mergeTrees(root1.right, root2.right);
        return merged;
    }
    public TreeNode mergeTrees2(TreeNode root1, TreeNode root2) {
        if (root1 == null) {
            return root2;
        }
        if (root2 == null) {
            return root1;
        }
        Queue<TreeNode> treeQueue1 = new LinkedList<>();
        Queue<TreeNode> treeQueue2 = new LinkedList<>();
        Queue<TreeNode> mergedQueue = new LinkedList<>();
        treeQueue1.offer(root1);
        treeQueue2.offer(root2);
        TreeNode ans = new TreeNode(root1.val + root2.val);
        mergedQueue.offer(ans);
        while (!treeQueue1.isEmpty() || !treeQueue2.isEmpty()) {
            TreeNode treeNode1 = treeQueue1.poll();
            TreeNode treeNode2 = treeQueue2.poll();
            TreeNode root = mergedQueue.poll();
            TreeNode mergedNode1, mergedNode2;
            if (treeNode1.left == null) {
                mergedNode1 = treeNode2.left;
            } else if (treeNode2.left == null) {
                mergedNode1 = treeNode1.left;
            } else {
                treeQueue1.offer(treeNode1.left);
                treeQueue2.offer(treeNode2.left);
                mergedNode1 = new TreeNode(treeNode1.left.val + treeNode2.left.val);
                mergedQueue.offer(mergedNode1);
            }
            root.left = mergedNode1;
            if (treeNode1.right == null) {
                mergedNode2 = treeNode2.right;
            } else if (treeNode2.right == null) {
                mergedNode2 = treeNode1.right;
            } else {
                treeQueue1.offer(treeNode1.right);
                treeQueue2.offer(treeNode2.right);
                mergedNode2 = new TreeNode(treeNode1.right.val + treeNode2.right.val);
                mergedQueue.offer(mergedNode2);
            }
            root.right = mergedNode2;
        }
        return ans;
    }
}
相关文章
|
3月前
【LeetCode 35】112.路径总和
【LeetCode 35】112.路径总和
33 0
|
3月前
【LeetCode 36】113.路径总和II
【LeetCode 36】113.路径总和II
35 0
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
280页PDF,全方位评估OpenAI o1,Leetcode刷题准确率竟这么高
【10月更文挑战第24天】近年来,OpenAI的o1模型在大型语言模型(LLMs)中脱颖而出,展现出卓越的推理能力和知识整合能力。基于Transformer架构,o1模型采用了链式思维和强化学习等先进技术,显著提升了其在编程竞赛、医学影像报告生成、数学问题解决、自然语言推理和芯片设计等领域的表现。本文将全面评估o1模型的性能及其对AI研究和应用的潜在影响。
59 1
|
4月前
|
数据采集 负载均衡 安全
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
本文提供了多个多线程编程问题的解决方案,包括设计有限阻塞队列、多线程网页爬虫、红绿灯路口等,每个问题都给出了至少一种实现方法,涵盖了互斥锁、条件变量、信号量等线程同步机制的使用。
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
|
3月前
【LeetCode 37】106.从中序与后序遍历构造二叉树
【LeetCode 37】106.从中序与后序遍历构造二叉树
28 0
|
3月前
【LeetCode 34】257.二叉树的所有路径
【LeetCode 34】257.二叉树的所有路径
28 0
|
4月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
5月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
67 6
|
5月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
133 2
|
5月前
|
索引 Python
【Leetcode刷题Python】从列表list中创建一颗二叉树
本文介绍了如何使用Python递归函数从列表中创建二叉树,其中每个节点的左右子节点索引分别是当前节点索引的2倍加1和2倍加2。
80 7