代码随想录算法训练营补打卡 day18|513.找树左下角的值、112. 路径总和、113.路径总和ii 、106.从中序与后序遍历序列构造二叉树

代码随想录

513.找树左下角的值

思路

层序遍历,遍历完后取出最后一层的第一个值

代码

class Solution {

    List<List<Integer>> tlist = new ArrayList<List<Integer>>();
    public int findBottomLeftValue(TreeNode root) {
        return levelOrder(root);

    }

    public int levelOrder(TreeNode cur){
        int val = 0;//保存最底层最左边节点的值

        Deque<TreeNode> q = new ArrayDeque<TreeNode>();
        q.addLast(cur);

        while(!q.isEmpty()){
            int len = q.size();
            List<Integer> list = new ArrayList<Integer>();
            while(len>0){
                TreeNode tnode = q.pollFirst();
                list.add(tnode.val);
                if(tnode.left!=null) q.addLast(tnode.left);
                if(tnode.right!=null) q.addLast(tnode.right);
                len--;
            }
            tlist.add(list);
        }
        val = tlist.get(tlist.size()-1).get(0);
        return val;

    }
}


题解思路

有两个关键,一是最后一行,二是最左边,可以通过最大深度的叶子节点判断是最后一行。只有第一次访问最大深度的时候,记录下节点值,按照中左右的顺序,那么访问的必然是最后一行最左边节点的值。

112. 路径总和 113.路径总和ii

思路

通过中序遍历,用一个res来保存最终的结果,只要有一个满足了根节点到叶子节点的路径和等于目标和的,那么就返回true。,并且每次回溯。

代码

class Solution {
    int sum = 0;
    boolean res = false;
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root == null) return false;
        sum += root.val;
        if(root.left == null && root.right==null){
            if( sum == targetSum)
            res = true;
            return res;
        }

        boolean t1 = false;
        if(root.left!=null){
            t1 = hasPathSum(root.left,targetSum);
            sum -= root.left.val;
        }
         boolean t2 =false;
        if(root.right!=null){
            t2 = hasPathSum(root.right,targetSum);
            sum -= root.right.val;
        }

        return res;
        
    }
}


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

思路

按照后序遍历的结果的最后一个数字找到中间节点,,然后切割中序遍历的 左边和右边,接着继续按照后续遍历的结果找到左边和右边的中间节点,切割中序遍历的下一个左边和右边…思路应该是递归。
题解思路:
• 第一步:如果数组大小为零的话,说明是空节点了。
• 第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。
• 第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点
• 第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)
• 第五步:切割后序数组,切成后序左数组和后序右数组
• 第六步:递归处理左区间和右区间

注意中序和前序、中序和后续都可以确定一颗二叉树,而前序和后序不能。

终点是通过下标 不断缩小中序数组和后续数组的范围,不改变原数组。每次获取中间节点的值即可 构造二叉树。
利用一个map确定中序数组的下标
注意要确定是左闭右开:在二分法中切割很重要

代码

class Solution {
    Map<Integer, Integer> map;  // 方便根据数值查找位置
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        map = new HashMap<>();
        for (int i = 0; i < inorder.length; i++) { // 用map保存中序序列的数值对应位置
            map.put(inorder[i], i);
        }

        return findNode(inorder,  0, inorder.length, postorder,0, postorder.length);  // 前闭后开
    }

    public TreeNode findNode(int[] inorder, int inBegin, int inEnd, int[] postorder, int postBegin, int postEnd) {
        // 参数里的范围都是前闭后开
        if (inBegin >= inEnd || postBegin >= postEnd) {  // 不满足左闭右开,说明没有元素,返回空树
            return null;
        }
        int rootIndex = map.get(postorder[postEnd - 1]);  // 找到后序遍历的最后一个元素在中序遍历中的位置
        TreeNode root = new TreeNode(inorder[rootIndex]);  // 构造结点
        int lenOfLeft = rootIndex - inBegin;  // 保存中序左子树个数,用来确定后序数列的个数
        root.left = findNode(inorder, inBegin, rootIndex,
                            postorder, postBegin, postBegin + lenOfLeft);
        root.right = findNode(inorder, rootIndex + 1, inEnd,
                            postorder, postBegin + lenOfLeft, postEnd - 1);

        return root;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值