day17 105. 从前序与中序遍历序列构造二叉树&&106. 从中序与后序遍历序列构造二叉树&&113. 路径总和 II&&112. 路径总和&&513. 找树左下角的值

  1. 从前序与中序遍历序列构造二叉树(LeetCode 105)
    核心思路:
    使用哈希表存储中序遍历中每个值的索引,以便快速查找。
    前序遍历的第一个元素是根节点。
    在中序遍历中找到根节点的位置,从而确定左子树和右子树的范围。
    递归构建左子树和右子树。
    时间复杂度:O(n),其中 n 是树的节点数。
    空间复杂度:O(n),主要来自递归调用栈和哈希表。
    //105. 从前序与中序遍历序列构造二叉树
    private Map<Integer, Integer> map1 = new HashMap<>();
    public TreeNode buildTree1(int[] preorder, int[] inorder) {
    if (preorder == null || inorder == null || preorder.length0 || inorder.length0) return null;
    for (int i = 0; i < inorder.length; i++) {
    map1.put(inorder[i], i);
    }
    return dfsBuildTree1(preorder,0,preorder.length-1,inorder,0,inorder.length-1);
    }
    private TreeNode dfsBuildTree1(int[] preorder,int pStart,int pEnd, int[] inorder,int inStart,int inEnd) {
    if (pStart > pEnd) return null;
    int val = preorder[pStart];
    int idx = map1.get(val);
    int leftSize=idx-inStart;//左子树中结点个数
    return new TreeNode(val,
    dfsBuildTree1(preorder,pStart+1,pStart+leftSize,inorder,inStart,idx-1),
    dfsBuildTree1(preorder,pStart+leftSize+1,pEnd,inorder,idx+1,inEnd)
    );
    }

  2. 从中序与后序遍历序列构造二叉树(LeetCode 106)
    核心思路:
    使用哈希表存储中序遍历中每个值的索引,以便快速查找。
    后序遍历的最后一个元素是根节点。
    在中序遍历中找到根节点的位置,从而确定左子树和右子树的范围。
    递归构建左子树和右子树。
    时间复杂度:O(n),其中 n 是树的节点数。
    空间复杂度:O(n),主要来自递归调用栈和哈希表。
    //106. 从中序与后序遍历序列构造二叉树
    private Map<Integer, Integer> map = new HashMap<>();
    public TreeNode buildTree(int[] inorder, int[] postorder) {
    if (inorder == null || postorder == null || inorder.length != postorder.length) {
    return null;
    }
    for (int i = 0; i < inorder.length; i++) {
    map.put(inorder[i], i);
    }
    return dfsBuildTree(inorder, 0, inorder.length - 1, postorder, 0, postorder.length - 1);
    }
    private TreeNode dfsBuildTree(int[] inorder, int inStart, int inEnd, int[] postorder, int postStart, int postEnd) {
    if (inStart > inEnd || postStart > postEnd) {
    return null;
    }
    // 后序数组的最后一个元素是当前子树的根节点
    int rootValue = postorder[postEnd];
    TreeNode root = new TreeNode(rootValue);
    // 在中序数组中找到根节点的位置
    int rootIndex = map.get(rootValue);
    // 左子树的节点数量
    int leftTreeSize = rootIndex - inStart;
    // 递归构建左子树
    root.left = dfsBuildTree(inorder, inStart, rootIndex - 1, postorder, postStart, postStart + leftTreeSize - 1);
    // 递归构建右子树
    root.right = dfsBuildTree(inorder, rootIndex + 1, inEnd, postorder, postStart + leftTreeSize, postEnd - 1);
    return root;
    }

  3. 路径总和 II(LeetCode 113)
    问题描述:给定一棵二叉树和一个目标和,找出所有从根节点到叶子节点的路径,使得路径上的节点值之和等于目标和。
    核心思路:
    使用深度优先搜索(DFS)遍历树。
    维护一个路径列表 path 和路径和 pathSum1。
    当到达叶子节点时,检查路径和是否等于目标和,如果是,则将路径加入结果列表。
    回溯时,移除当前节点并更新路径和。
    时间复杂度:O(n),其中 n 是树的节点数。
    空间复杂度:O(n),主要来自递归调用栈和路径列表。
    //113. 路径总和 II
    private int pathSum1;

    public List<List> pathSum(TreeNode root, int targetSum) {
    List<List> res = new ArrayList<>();
    List path = new LinkedList<>();
    if (root == null) {
    return res;
    }
    dfsPathSum(root, res, path, targetSum);
    return res;
    }

    private void dfsPathSum(TreeNode root, List<List> res, List path, int targetSum) {
    if (root == null) return;
    path.add(root.val);
    pathSum1 += root.val;
    if (root.left == null && root.right == null) {
    if (pathSum1 == targetSum) {
    res.add(new ArrayList<>(path));
    }
    path.remove(path.size() - 1);
    pathSum1 -= root.val;
    return;
    }
    if (root.left != null) {
    dfsPathSum(root.left, res, path, targetSum);
    }
    if (root.right != null) {
    dfsPathSum(root.right, res, path, targetSum);
    }
    path.remove(path.size() - 1);
    pathSum1 -= root.val;
    }

  4. 路径总和(LeetCode 112)
    问题描述:给定一棵二叉树和一个目标和,判断是否存在从根节点到叶子节点的路径,使得路径上的节点值之和等于目标和。
    核心思路:
    使用深度优先搜索(DFS)遍历树。
    维护一个路径和 pathSum。
    当到达叶子节点时,检查路径和是否等于目标和。
    回溯时,更新路径和。
    时间复杂度:O(n),其中 n 是树的节点数。
    空间复杂度:O(n),主要来自递归调用栈。
    //112. 路径总和
    private int pathSum;

    public boolean hasPathSum(TreeNode root, int targetSum) {
    if (root == null) return false;
    return dfsHasPathSum(root, targetSum);
    }

    private boolean dfsHasPathSum(TreeNode root, int targetSum) {
    if (root == null) return false;
    pathSum += root.val;
    if (root.left == null && root.right == null && pathSum == targetSum) {
    return true;
    }
    boolean flag1 = dfsHasPathSum(root.left, targetSum);
    boolean flag2 = dfsHasPathSum(root.right, targetSum);
    pathSum -= root.val;
    return flag1 || flag2;
    }

  5. 找树左下角的值(LeetCode 513)
    问题描述:给定一棵二叉树,找到树的左下角的值(即最深的左叶子节点的值)。
    核心思路:
    使用深度优先搜索(DFS)遍历树。
    维护当前的最大高度 curHeight 和对应的值 curVal。
    先遍历左子树,再遍历右子树,确保最深的左叶子节点的值被记录。
    时间复杂度:O(n),其中 n 是树的节点数。
    空间复杂度:O(n),主要来自递归调用栈。
    //513. 找树左下角的值
    private int curVal;
    private int curHeight;

    public int findBottomLeftValue(TreeNode root) {
    //层序遍历实现,效率低 4ms
    /Queue queue = new LinkedList<>();
    queue.add(root);
    List<List> list = new ArrayList<>();
    while (!queue.isEmpty()) {
    List list1 = new ArrayList<>();
    int size = queue.size();
    for (int i = 0; i < size; i++) {
    TreeNode node = queue.poll();
    list1.add(node.val);
    if (node.left != null) {
    queue.add(node.left);
    }
    if (node.right != null) {
    queue.add(node.right);
    }
    }
    list.add(list1);
    }
    return list.get(list.size()-1).get(0);
    /
    //递归实现,跟右视图做法一样 效率高 0ms
    dfsFindBottomLeftValue(root, 0);
    return curVal;
    }

    private void dfsFindBottomLeftValue(TreeNode root, int height) {
    if (root == null) {
    return;
    }
    height += 1;
    if (height > curHeight) {
    curHeight = height;
    curVal = root.val;
    }
    dfsFindBottomLeftValue(root.left, height);//先在左子树找
    dfsFindBottomLeftValue(root.right, height);
    }

posted @   123木头人-10086  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示