day16 二叉树-左下角+路径SumTarget+由后序中序遍历构建二叉树(难难难)

### 6.14 513. Find Bottom Left Tree Value
Given the root of a binary tree, return the leftmost value in the last row of the tree.
https://programmercarl.com/0513.%E6%89%BE%E6%A0%91%E5%B7%A6%E4%B8%8B%E8%A7%92%E7%9A%84%E5%80%BC.html  
1.判断底部:深度最大的叶子节点就在底部
2.判断最左:优先遍历左孩子。注意:底部最左的节点不一定是左节点。
```java
public class leftBottomLeave {  
    private int depth = -1;  
    private int result = 0;  
    public int findBottomLeftValue(TreeNode root) {  
        result = root.val;  
        bottomLeftTraversal(root,0);  
        return result;  
    }  
    private void bottomLeftTraversal(TreeNode node, int depth){  
        //叶子节点  
        if(node.left == null && node.right == null){  
            //当当前深度大于最大深度时, 更新深度,并更新叶子值  
            if(depth > this.depth){  
                this.depth = depth;  
                this.result = node.val;  
            }  
        }  
        //如何判断节点是最左节点?只要先遍历左节点即可。最大深度会由左叶子确定,后序再有相同深度的新的右叶子,也没办法进入if(depth > this.depth)循环了。从而无法覆盖result。  
        if(node.left != null){  
            depth++;  
            bottomLeftTraversal(node.left,depth);  
            depth--;  
        }  
        if(node.right != null){  
            depth++;  
            bottomLeftTraversal(node.right,depth);  
            depth--;  
        }  
    }  
}  
class leftBottomLeaveTest {  
    public static void main(String[] args) {  
        TreeBuilder tb = new TreeBuilder();  
        TreeNode root = tb.buildTree();  
  
        leftBottomLeave example = new leftBottomLeave();  
        int i  = example.findBottomLeftValue(root);  
        System.out.println(i);  
    }  
}
```

### 6.15 112. Path Sum
Given the root of a binary tree and an integer targetSum, return true if the tree has a root-to-leaf path such that adding up all the values along the path equals targetSum.
A leaf is a node with no children.
https://programmercarl.com/0112.%E8%B7%AF%E5%BE%84%E6%80%BB%E5%92%8C.html  
```java
public class pathSumTarget {  
    public boolean hasPathSum(TreeNode root, int targetSum) {  
        if (root == null) return false;  
        // 从当前节点开始计算路径和(回溯)  
        int currentSum = targetSum - root.val;  
        // 如果是叶子节点,并且路径和为0,则返回true  
        if (root.left == null && root.right == null) {  
            return currentSum == 0;  
        }  
        // 递归检查左子树和右子树  
        //return hasPathSum(root.left, currentSum) || hasPathSum(root.right, currentSum);  
        boolean flagLeft = hasPathSum(root.left, currentSum);  
        boolean flagRight = hasPathSum(root.right, currentSum);  
        return flagLeft || flagRight;  
    }  
}  
class pathSumTargetTest {  
    public static void main(String[] args) {  
        TreeBuilder tb = new TreeBuilder();  
        TreeNode root = tb.buildTree();  
  
        pathSumTarget example = new pathSumTarget();  
        boolean i  = example.hasPathSum(root,16);  
        System.out.println(i);  
    }  
}
```


### 6.16 106. Construct Binary Tree from Inorder and Postorder Traversal
Given two integer arrays inorder and postorder where inorder is the inorder traversal of a binary tree and postorder is the postorder traversal of the same tree, construct and return the binary tree.
https://programmercarl.com/0106.%E4%BB%8E%E4%B8%AD%E5%BA%8F%E4%B8%8E%E5%90%8E%E5%BA%8F%E9%81%8D%E5%8E%86%E5%BA%8F%E5%88%97%E6%9E%84%E9%80%A0%E4%BA%8C%E5%8F%89%E6%A0%91.html 

第一步:如果数组大小为零的话,说明是空节点了。
第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。
第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点
第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)
第五步:切割后序数组,切成后序左数组和后序右数组
第六步:递归处理左区间和右区间
图解:

![[二叉树1-15.png]]
![[106. Construct Binary Tree from Inorder and Postorder Traversal.png]]
```java
public class constructBT {  
    //建立一个map用来存储inorder。为什么只要inorder呢?因为inorder需要通过数值来查找下标,而postorder不需要。  
    Map<Integer,Integer> mapInorder;  
    public TreeNode buildTree(int[] inorder, int[] postorder) {  
        mapInorder = new HashMap<>();  
        for (int i = 0; i < inorder.length; i++) {  
            mapInorder.put(inorder[i],i);  
        }  
        return getNodes(inorder,0,inorder.length,postorder,0,postorder.length);  
    }  
    private TreeNode getNodes(int[] inorder, int inStart, int inEnd, int[] postorder, int postStart, int postEnd){  
        //如果为空,直接返回空  
        if(inStart >= inEnd || postStart >= postEnd) return null;  
  
        int val = postorder[postEnd-1];  
        TreeNode node = new TreeNode(val);//构造节点  
        int midPosition = mapInorder.get(val);  
        int lenOfLeft = midPosition-inStart;//左子树的节点个数  
        //用中序遍历得到的左子树的节点个数去定位后序遍历左子树的节点  
        node.left = getNodes(inorder, inStart, midPosition, postorder, postStart, postStart + lenOfLeft);  
        //中序遍历:左中右,后序遍历:左右中。  
        //中序遍历数组从midPosition+1开始,因为midPosition的node已经被记录了。
        node.right = getNodes(inorder, midPosition + 1, inEnd, postorder, postStart + lenOfLeft, postEnd-1);  
  
        return node;  
    }  
}  
class constructBTTest {  
    public static void main(String[] args) {  
        int[] inorder = {8,4,9,2,10,5,11,1,12,6,13,3,14,7,15};  
        int[] postorder = {8,9,4,10,11,5,2,12,13,6,14,15,7,3,1};  
        constructBT cbt  = new constructBT();  
        TreeNode node = cbt.buildTree(inorder,postorder);  
  
        List<List<Integer>> list = levelOrder(node);  
        for(List<Integer> levels :list){  
            System.out.print("[");  
            for(int nums : levels){  
                System.out.print(nums+" ");  
            }  
            System.out.println("]");  
        }  
    }  
    public static List<List<Integer>> levelOrder(TreeNode root) {  
        List<List<Integer>> result = new LinkedList<>(); 
        if(root == null) return result;  
  
        Deque<TreeNode> deque = new LinkedList<>();  
        deque.offerLast(root);  
  
        while(!deque.isEmpty()){  
            int size = deque.size();  
            List<Integer> levelNums = new LinkedList<>(); 
            while(size > 0){  
                TreeNode node = deque.peekFirst();  
                levelNums.add(node.val);  
                deque.pollFirst();
                if(node.left != null) deque.offerLast(node.left);  
                if(node.right != null) deque.offerLast(node.right);  
                size--;  
            }  
            result.add(levelNums);  
        }  
        return result;  
    }  
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值