代码随想录day16 二叉树

513.找树左下角的值

给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。

假设二叉树中至少有一个节点。

层序遍历,只不过是右边的节点先入队,所以最后的就是左边节点的值。

class Solution {
    public int findBottomLeftValue(TreeNode root) {
        Deque<TreeNode> deque = new LinkedList<>();
        deque.offer(root);
        int res = 0;
        while (!deque.isEmpty()) {
            int size = deque.size();
            for (int i = 0; i < size; i++) {
                TreeNode curr = deque.poll();
                if (curr.right != null) {
                    deque.offer(curr.right);
                }
                if (curr.left != null) {
                    deque.offer(curr.left);
                }
                res = curr.val;
            }
        }
        return res;
    }

112.路径总和

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。

叶子节点 是指没有子节点的节点。
代码随想录day16 二叉树_第1张图片

方法一:dfs

以targetSum为初始值,遍历到哪个节点减去它的值,如果到叶节点sum和叶节点的值相同,那么就有这样的路径

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if (root == null) {
            return false;
        }
        if (root.left == null && root.right == null) {
            return root.val == targetSum;
        }
        return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);

    }

方法二:bfs

使用两个队列,分别存储将要遍历的节点,以及根节点到这些节点的路径和。注意在while循环内部就不用遍历了。

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if (root == null) {
            return false;
        }
        Deque<TreeNode> deque = new LinkedList<>();
        Deque<Integer> dequeVal = new LinkedList<>();
        deque.offer(root);
        dequeVal.offer(root.val);
        while (!deque.isEmpty()) {
            TreeNode curr = deque.poll();
            int temp = dequeVal.poll();
            if (curr.left == null && curr.right == null) {
                if (temp == targetSum) {
                    return true;
                }
                continue;
            }
            if (curr.left != null) {
                deque.offer(curr.left);
                dequeVal.offer(curr.left.val + temp);
            }
            if (curr.right != null) {
                deque.offer(curr.right);
                dequeVal.offer(curr.right.val + temp);
            }
        }
        return false;
    }
}

113.路径总和II

就是在上一题的基础上把路径输出。
使用path(队列,感觉也可以用ArrayList)存储路径。dfs从node开始,分左右子节点向下寻找。如果这个节点访问完,那么就把这个节点从队列中移除,再去另一边寻找(所以需要出队操作)。

class Solution {
    List<List<Integer>> res = new LinkedList<List<Integer>>();
    Deque<Integer> path = new LinkedList<>();

    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        dfs(root, targetSum);
        return res;
    }

    public void dfs(TreeNode node, int sum) {
        if (node == null) {
            return;
        }
        path.offer(node.val);
        if (node.left == null && node.right == null && node.val == sum) {
            res.add(new LinkedList<Integer>(path));
        }
        dfs(node.left, sum - node.val);
        dfs(node.right, sum - node.val);
        path.pollLast();
    }
}

106.从中序和后序遍历构建二叉树

代码随想录day16 二叉树_第2张图片
核心思路
​1.后序遍历特性:postorder 的最后一个元素是当前子树的根节点。
​2.中序遍历分割:找到根节点在中序遍历 inorder 中的位置,左侧为左子树,右侧为右子树。
3.​递归构造:根据根节点分割中序和后序数组,分别构造左子树和右子树。

class Solution {
    int[] inorder;
    int[] postorder;
    Map<Integer, Integer> map_idx = new HashMap<>();

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

    public TreeNode build(int inleft, int inright, int postleft, int postright) {
        if (inleft > inright || postleft > postright) {
            return null;
        }
        // 后序遍历的最后一个元素是根节点
        int rootVal = postorder[postright];
        TreeNode root = new TreeNode(rootVal);
        // 在中序中找到根节点的索引
        int rootIndex = map_idx.get(rootVal);
        int leftNodeCount = rootIndex - inleft;
        // 递归构造左子树和右子树
        root.left = build(inleft, rootIndex - 1, postleft, postleft + leftNodeCount - 1);
        root.right = build(rootIndex + 1, inright, postleft + leftNodeCount, postright - 1);
        return root;
    }
}

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

和前面的一样,改一下前序序列的起始点就可以了

class Solution {
    int[] preorder;
    int[] inorder;
    Map<Integer, Integer> map_idx = new HashMap<>();

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

    public TreeNode build(int inleft, int inright, int preleft, int preright) {
        if (inleft > inright || preleft > preright) {
            return null;
        }
        // 前序遍历的第一个节点是根节点
        int rootVal = preorder[preleft];
        TreeNode root = new TreeNode(rootVal);
        // 在中序遍历中找到根节点
        int rootIndex = map_idx.get(rootVal);
        int leftNodeCount = rootIndex - inleft;

        root.left = build(inleft, rootIndex - 1, preleft + 1, preleft + 1 + leftNodeCount);
        root.right = build(rootIndex + 1, inright, preleft + 1 + leftNodeCount, preright);
        return root;
    }
}

你可能感兴趣的:(java,算法,数据结构)