算法训练营第十八天|513.找树左下角的值、112. 路径总和、113.路径总和ii、106.中序与后序构造二叉树、105.前序与中序构造二叉树

51 阅读2分钟

513. 找树左下角的值

class Solution {
    public int findBottomLeftValue(TreeNode root) {
        Deque<TreeNode> q = new LinkedList<>();
        q.offer(root);
        int res = 0;

        while(!q.isEmpty()){
            int size = q.size();
            for(int i = 0; i < size; i++){
                TreeNode node = q.poll();
                if(i == 0)res = node.val;
                if(node.left != null)q.offer(node.left);
                if(node.right != null)q.offer(node.right);
            }
        }

        return res;
    }
}

112. 路径总和

遍历的路线,并不要遍历整棵树,所以递归函数需要返回值。

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root == null){
            return false;
        }
        if(root.val == targetSum && root.left == null && root.right == null){
            return true;
        }
        // 把targetSum - root.val作为参数传入,函数结束后targetSum没有改变,蕴藏着回溯思想
        return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
    }
}

113. 路径总和 II

要遍历整个树,找到所有路径,所以递归函数不要返回值

class Solution {
    LinkedList<Integer> path = new LinkedList<>();
    List<List<Integer>> res = new LinkedList<>();
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        backtracking(root, path, targetSum);
        return res;
    }
    private void backtracking(TreeNode node, LinkedList<Integer> path, int targetSum){
        // Base case: if the node is null, just return
        if(node == null) return;
        
        // Add the current node's value to the current path
        path.add(node.val);
        
        // Check if we've reached a leaf node and if the path's sum matches the target sum
        if(targetSum == node.val && node.left == null && node.right == null){
            // If both conditions are met, add a copy of the path to the results
            res.add(new LinkedList<>(path));
        } else { // If not at a leaf node or path's sum doesn't match the target sum, continue exploring
        
            // Explore the left child
            backtracking(node.left, path, targetSum - node.val);
            // Explore the right child
            backtracking(node.right, path, targetSum - node.val);
        }
        
        // Backtrack: remove the last node from the path to explore other possibilities
        path.removeLast();
    }
}

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

class Solution {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        if(inorder.length == 0 || postorder.length == 0){
            return null;
        }
        return traversal(inorder, 0, inorder.length, postorder, 0, postorder.length);
    }
    private TreeNode traversal(int[] inorder, int inorderStart, int inorderEnd, int[] postorder, int postorderStart, int postorderEnd){
        // 第一步:如果数组大小为零的话,说明是空节点了。
        if(postorderStart == postorderEnd)return null;

        // 第二步:如果不为空,那么取后序数组最后一个元素作为当前根节点元素。
        int rootVal = postorder[postorderEnd - 1];
        TreeNode root = new TreeNode(rootVal);

        // 第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点
        int cutPoint;
        for(cutPoint = inorderStart; cutPoint < inorderEnd; cutPoint++){
            if(inorder[cutPoint] == rootVal)break;
        }

        // 第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)
        int leftInorderStart = inorderStart;
        int leftInorderEnd = cutPoint;

        int rightInorderStart = cutPoint + 1;
        int rightInorderEnd = inorderEnd;

        // 第五步:切割后序数组,切成后序左数组和后序右数组
        int leftPostorderStart = postorderStart;
        int leftPostorderEnd = postorderStart + (cutPoint - inorderStart);

        int rightPostorderStart = leftPostorderEnd;
        int rightPostorderEnd = postorderEnd - 1;
        
        // 第六步:递归处理左区间和右区间
        root.left = traversal(inorder, leftInorderStart, leftInorderEnd, postorder, leftPostorderStart, leftPostorderEnd);
        root.right = traversal(inorder, rightInorderStart, rightInorderEnd, postorder, rightPostorderStart, rightPostorderEnd);

        return root;
    }
}

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

class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if(preorder.length == 0 || inorder.length == 0){
            return null;
        }
        return traversal(preorder, 0, preorder.length, inorder, 0, inorder.length);
    }
    private TreeNode traversal(int[] preorder, int preorderStart, int preorderEnd, int[] inorder, int inorderStart, int inorderEnd){
        if(preorderStart == preorderEnd)return null;

        int rootVal = preorder[preorderStart];
        TreeNode root = new TreeNode(rootVal);

        int cutPoint;
        for(cutPoint = inorderStart; cutPoint < inorderEnd; cutPoint++){
            if(inorder[cutPoint] == rootVal)break;
        }

        int leftInorderStart = inorderStart;
        int leftInorderEnd = cutPoint;

        int rightInorderStart = cutPoint + 1;
        int rightInorderEnd = inorderEnd;

        int leftPreorderStart = preorderStart + 1;
        int leftPreorderEnd = preorderStart + 1 + (cutPoint - inorderStart);

        int rightPreorderStart = leftPreorderEnd;
        int rightPreorderEnd = preorderEnd;

        root.left = traversal(preorder, leftPreorderStart, leftPreorderEnd, inorder, leftInorderStart, leftInorderEnd);
        root.right = traversal(preorder, rightPreorderStart, rightPreorderEnd, inorder, rightInorderStart, rightInorderEnd);

        return root;
    }
}