代码随想录刷题|LeetCode 513. 找树左下角的值 112. 路径总和 113.路径总和|| 106. 从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树

发布于:2022-10-30 ⋅ 阅读:(292) ⋅ 点赞:(0)

513.找树左下角的值

题目链接:力扣

思路

        层序遍历的思路还是很好得到的,在每层的遍历中我们都可以得到最左边的数字,那么也是可以得到最底层的最左边的数字的,比递归法简单多了

        使用递归的话也是可以找到最底层最左侧的值——最后一行找到最左侧的值,我们只要找到这棵树得最大深度,然后记录这层从左侧第一个值就可以了
        那么前序(中左右)、后序(左右中)、中序(左中右),都是可以的,因为不论是那种顺序的遍历,每一层都是会先处理左边再处理右边,这道题目没有中间节点处理的逻辑
        所以通过递归要做两件事:
                1、找到树的最大深度
                2、记录最大深度的最左侧的值

找树左下角的值

递归法

        定义一个变量,表示最大深度,记录所有深度中的最大深度
        定义一个变量,表示结果,每层记录结果,最后结果中保存的是深度最大的一层的结果

        递归函数:
                处理根节点的参数,还有一个参数depth,记录当前深度

        终止条件:
                当遇到叶子节点的时候,就需要统计一下最大的深度了,并且更新值
                通俗的想,直到找到最底层、最左侧的节点,我们就可以进行终止了
                在遍历的时候,不论是哪种序的遍历方法,对当前层来说,总是左节点先进来判断的
                而这里利用这个特性,深度加深,此层的第一个节点进来,判断,记录当前最大深度,然后记录节点的值,此时深度更新完毕,最左侧节点更新完毕

class Solution {
    public int findBottomLeftValue(TreeNode root) {
        // 根节点和其对应的深度
        traversal(root,1);
        return result;
    }


    int maxDepth = Integer.MIN_VALUE; //用来存放最大深度的
    int result = 0; // 当深度增加时,保存这一层的第一个值

    // 首先确定递归函数
    void traversal(TreeNode node, int depth) {
        if (node == null) {
            return;
        }

        if (node.left == null && node.right == null) {
            // 说明node是一个叶子节点
            if (depth > maxDepth) {
                maxDepth = depth;
                result = node.val;
            }
        }

        // 左
        if (node.left != null) {
            // 那就得探探你的深度了,找到你这边深度最大的叶子节点了
            // 注意哈:traversal()的两个参数代表的意思是;这个节点,这个节点的深度
            depth++;
            traversal(node.left,depth);
            depth--;
        }

        // 右
        if (node.right != null) {
            depth++;
            traversal(node.right,depth);
            depth--;
        } 

        // 中
        // 中不做处理
    }
}

 迭代法

        层序遍历,简单易懂好操作

class Solution {
    public int findBottomLeftValue(TreeNode root) {

        // 设这个要查找的值为0,使用层序遍历
        // 每次遍历一层就将这个值重新赋值一下
        int result = 0;

        Deque<TreeNode> deque = new ArrayDeque<>();
        deque.offer(root);
        while (!deque.isEmpty()) {
            int len = deque.size();
            TreeNode leftnode = deque.peek();
            result = leftnode.val;
            for (int i = 0; i < len; i++) {
                TreeNode node = deque.poll();
                if (node.left != null) {
                    deque.offer(node.left);
                } 
                if (node.right != null) {
                    deque.offer(node.right);
                }
            }
        }
        return result;
    }
}

112.路径总和

题目链接:力扣

思路

        求出所有根节点到叶子节点的值的总和,然后看看其中有没有和目标值相等的值

        那就需要收割所有路径的值,这跟 257.二叉树的所有路径 比较像,只不过多了一步处理

路径总和

递归法(全部遍历)

        太激动了,第一次自己完整地写出来一道递归的题目

根据257的写法:

        这种方法对于求所有的路径是很合适的,因为你一定要把所有的路径都添加进去。

        但是这个题目没必要把左右的路径全部算出来,只要有符合路径的结果就可以了

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {

        List<TreeNode> nodes = new ArrayList<>();
        List<Integer> allValue = new ArrayList<>();

        if (root == null) {
            return false;
        }

        nodesSum(root,nodes,allValue);

        return allValue.contains(targetSum);

    }

    void nodesSum(TreeNode node, List<TreeNode> nodes, List<Integer> allValue) {

        // 中
        nodes.add(node);

        // 终止条件
        if (node.left == null && node.right == null) {
            // 说明碰到这条路径的最后叶子节点了,收集这条路径上的结果
            int sum = 0;
            for (TreeNode value : nodes) {
                sum += value.val;
            }
            allValue.add(sum);
        }

        // 左
        if (node.left != null) {
            nodesSum(node.left,nodes,allValue);
            nodes.remove(nodes.size() - 1);
        }
        // 右
        if (node.right != null) {
            nodesSum(node.right,nodes,allValue);
            nodes.remove(nodes.size() - 1);
        }

    }
}

递归法(不用全部遍历)

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if (root == null) {
            return false;
        }

        return traversal(root,targetSum - root.val);
    }

    boolean traversal(TreeNode cur,int count) {
        // 终止条件
        // 遇到了叶子节点,并且目标值被减到0
        if (cur.left == null && cur.right == null && count == 0) {
            return true;
        }
        // 遇到了叶子节点,但是目标值没有被减到0
        if (cur.left == null && cur.right == null) {
            return false;
        }

        // 左
        if (cur.left != null) {
            count -= cur.left.val;
            if (traversal(cur.left,count)) {
                return true;
            }
            count += cur.left.val;
        }

        // 右
        if (cur.right != null) {
            count -= cur.right.val;
            if (traversal(cur.right,count)) {
                return true;
            }
            count += cur.right.val;
        }

        return false;
    }
}

113.路径总和||

题目链接:力扣

思路

        跟257、二叉树的所有路径 力扣 112 路径总和 力扣 的原理是一样的,只是对结果的处理上有所不同

路径总和||

        需要注意的点是:

                在将List<Integer>添加到List<List<Integer>>中时,一定要新创建一个集合来保存结果,否则这个集合会被后面的程序改变,因为集合中保存的是内存地址
     <--------错误实例:          

class Solution {
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {

        List<List<Integer>> result = new ArrayList<>();
        List<Integer> nodeVals = new ArrayList<>();

        if (root == null) {
            return  result;
        }

        nodesList(root,nodeVals,result,targetSum);
        return result;
    }

    void nodesList(TreeNode node,List<Integer> nodeVals,List<List<Integer>> result,int targetSum){

        // 中
        nodeVals.add(node.val);

        // 终止条件
        if (node.left == null && node.right == null) {
            int sum = 0;
            for (Integer nodeVal : nodeVals) {
                sum += nodeVal;
            }
            if (sum == targetSum) {
                // 要重新创建一个集合对象来保存这里的值,集合中只能保存地址
                result.add(new ArrayList<>(nodeVals));
            }
        }

        // 左
        if (node.left != null) {
            nodesList(node.left,nodeVals,result,targetSum);
            nodeVals.remove(nodeVals.size() - 1);
        }
        // 右
        if (node.right != null) {
            nodesList(node.right,nodeVals,result,targetSum);
            nodeVals.remove(nodeVals.size() - 1);
        }
        
    }
}

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

题目链接

思路

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

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

题目链接

思路

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

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到