代码随想录训练营day18, 找树左下角的值, 路径总和, 从中序与后序/前序中序遍历序列构造二叉树

 找树左下角的值

递归法: 比较复杂, 直接拉代码:

class Solution {
    private int Deep = -1;
    private int value = 0;
    public int findBottomLeftValue(TreeNode root) {
        value = root.val;
        findLeftValue(root,0);
        return value;
    }

    private void findLeftValue (TreeNode root,int deep) {
        if (root == null) return;
        if (root.left == null && root.right == null) {
            if (deep > Deep) {
                value = root.val;
                Deep = deep;
            }
        }
        if (root.left != null) findLeftValue(root.left,deep + 1);
        if (root.right != null) findLeftValue(root.right,deep + 1);
    }
}

迭代法: 这个是很秒的, 左下角的值正好就是最后一层的第一个值, 所以直接peek就行了

class Solution {
    public int findBottomLeftValue(TreeNode root) {
        //迭代法定义一个队列
        Queue<TreeNode> que = new LinkedList<>();
        if(root == null){
            return 0;
        }
        que.offer(root);
        int res = 0;
        while(!que.isEmpty()){
            int size = que.size();
            //左下角的值, 就是最后一层第一个
            int res = que.peek().val;
            while(size-- > 0){
                TreeNode cur = que.poll();
                if(cur.left != null){
                    que.offer(cur.left);
                }
                if(cur.right != null){
                    que.offer(cur.right);
                }
            }
        }
        return res;
    }
}

路径总和

递归法, 用前序就行

思路: 每次遍历节点, 就要targetSum -= root.val, 遍历到叶子节点, 同时sum = 0时, 说明找到了路径

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root == null){
            return false;
        }
        //每次遍历一个节点, 减去节点的val
        targetSum -= root.val;
        //中, 就是遍历到叶子节点时, 看最后值是否为0
        if(root.left == null && root.right == null){
            return targetSum == 0;
        }
        //继续递归, 不要让空节点进入递归
        if(root.left != null){
            boolean left = hasPathSum(root.left, targetSum);
            //判断有没有找到
            if(left) return true;
        }
        if(root.right != null){
            boolean right = hasPathSum(root.right, targetSum);
            //判断有没有找到
            if(right) return true;
        }
        return false;
    }
}
//精简版:
class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root == null){
            return false;
        }
        if(root.left == null && root.right == null){
            return  targetSum == root.val;
        }
        return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
    }
}

迭代法:

定义两个栈, 一个栈用来遍历和之前的一样, 另一个栈用来收集sum, 和层序遍历的区别就是, 只要保证判断在叶子节点时, sum==targetSum, 就return true, 否则在while循环外面return false

路径总和II

前序, 和之前的找出所有路径有点相似, 但是多了回溯的思想

class Solution {
    List<List<Integer>> res = new LinkedList<>();
    Deque<Integer> path = new LinkedList<>();
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        dfs(root, targetSum);
        return res;

    }

    public void dfs(TreeNode root, int targetSum){
        if(root == null){
            return;
        }
        先把根节点数值放在队列, 然后定义targetSum
        path.offer(root.val);
        targetSum -= root.val;
        if(root.left == null && root.right == null && targetSum == 0){
            //因为上面定义的list是公用的, 所以要里面创建下
            res.add(new LinkedList<Integer>(path));
        }
        //继续递归
        dfs(root.left, targetSum);
        dfs(root.right, targetSum);
        //这里需要回溯, 把path给poll出来
        path.pollLast();
    }
}

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

  1. 首先创建一个HashMap, 然后遍历保存中序序列
  2. 然后solution方法内return(preorder, 0, preorder.length, inorder, 0, inorder.length)左闭右开
  3. 创建递归方法, 因为return参数是左闭右开, 所有终止条件是>=和<=
  4. 先传入根节点, 然后根据下图定义inorder里的根节点位置pIndex = map.get(rootVal)
  5. 最后调用递归, left传入前序左子树参数, 和中序左子树参数, right同理
  6. 最后返回root

class Solution {
    //*可选,因为树中没有重复元素,所以,可以开始用哈希表存储inorder的值和对应的索引
    Map<Integer, Integer> inorderMap = new HashMap<>();
    public TreeNode buildTree(int[] preorder, int[] inorder) {
				//先把中序数组遍历放到map里面
        for(int i = 0; i < inorder.length; i++){
            inorderMap.put(inorder[i], i);
        }
				//return递归方法, 这里就是前序数组和中序数组的左右
        //我这里对于边界的定义是左闭右开, 要注意	
        return build(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
    }
		//因为是造树, 所以要递归方法要return TreeNode
    public TreeNode build(int[] preorder, int preStart, int preEnd, int[] inorder, int inStart, int inEnd){
        //先写个结束条件, 符合左闭右开
        if(inStart > inEnd || preStart > preEnd){
            return null;
        }

        //导入根节点
        int rootVal = preorder[preStart];
        TreeNode root = new TreeNode(rootVal);
				//定义中序Index根节点
        int index = inorderMap.get(rootVal);

        开始递归
        root.left = build(preorder, preStart + 1, index - inStart + preStart,
                                     inorder, inStart, index - 1);
        root.right = build(preorder, index - inStart + preStart + 1, preEnd,
                                    inorder, index + 1, inEnd);
        return root;
    }
}

 中序和后序构造二叉树

五步走:

  1. 后序数组为0, 空节点
  2. 后续数组最后一个元素为节点元素
  3. 寻找中序数组位置, 做切割点
  4. 切中序数组
  5. 切后序数组
  6. 递归处理左区间右区间
  7. class Solution {
        //*可选,因为树中没有重复元素,所以,可以开始用哈希表存储inorder的值和对应的索引
        Map<Integer, Integer> inorderMap = new HashMap<>();
        public TreeNode buildTree(int[] inorder, int[] postorder) {
            for(int i = 0; i < inorder.length; i++){
                inorderMap.put(inorder[i], i);
            }
            return build(inorder, 0, inorder.length - 1, postorder, 0, postorder.length - 1);
        }
    
        public TreeNode build(int[] inorder, int inStart, int inEnd, int[] postorder, int postStart, int postEnd){
            //最后写递归出口,base  case
            if(inStart > inEnd || postStart > postEnd){
                return null;
            }
    
            //1.确定根节点
            int rootVal = postorder[postEnd];
            //1.1做出根节点
            TreeNode root = new TreeNode(rootVal);
            int index = inorderMap.get(rootVal);
    
            //2.1计算inorder中左子树的数目,以此确定后序中左右子树的边界
            int num_left_tree = index - inStart;
            //3.递归构造左右子树
            root.left = build(inorder, inStart, index - 1, 
                                postorder, postStart, postStart + num_left_tree - 1);
            root.right = build(inorder, index + 1, inEnd, 
                                postorder, postStart + num_left_tree, postEnd - 1);
            return root;
        }
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值