小工具知识网

当前位置: 首页 > 行业知识 > 代码随想录算法训练营第18天|513.找树左下角的值、112.路径总和、113.路径总和二、106.从中序与后序遍历序列构造二叉树、105.从前序与中序遍历序列构造二叉树

行业知识

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

2026-11-02 06:27:31 来源:互联网转载

目录

  • 一、力扣513.找树左下角的值
    • 1.1 题目
    • 1.2 思路
    • 1.3 代码
    • 1.4 总结
    • 二、力扣112.路径总和
      • 2.1 题目
      • 2.2 思路
      • 2.3 代码
      • 2.4 总结
      • 三、力扣113.路径总和二
        • 3.1 题目
        • 3.2 思路
        • 3.3 代码
        • 3.4 总结
        • 四、力扣106.从中序与后序遍历序列构造二叉树
          • 4.1 题目
          • 4.2 思路
          • 4.3 代码
          • 4.4 总结
          • 五、力扣105.从前序与中序遍历序列构造二叉树
            • 5.1 题目
            • 5.2 思路
            • 5.3 代码
            • 5.4 ���结

              一、力扣513.找树左下角的值

              1.1 题目

              1.2 思路

              迭代

              我的思路:层序遍历,寻找最后一层的第一个值,可以用一个集合记录每一层的第一个节点的数值,遍历结束后输出集合的最后一个值。

              递归+回溯

              1.确定递归函数的参数和返回值

              参数必须有要遍历的树的根节点,还有就是一个int型的变量用来记录最长深度。 这里就不需要返回值了,所以递归函数的返回类型为void。

              本题还需要类里的两个全局变量,maxLen用来记录最大深度,result记录最大深度最左节点的数值。

              2.确定终止条件

              当遇到叶子节点的时候,就需要统计一下最大的深度了,所以需要遇到叶子节点来更新最大深度。

              3.确定单层递归的逻辑

              在找最大深度的时候,递归的过程中依然要使用回溯。

              1.3 代码

              迭代

              class Solution {    public int findBottomLeftValue(TreeNode root) {        //迭代法,层序遍历        Queue que = new LinkedList();        List res = new ArrayList();        if(root == null){            return root.val;        }        que.offer(root);        while(!que.isEmpty()){            int size = que.size();            int startSize = size;            while(size > 0){                TreeNode cur =  que.poll();                if(size == startSize){                    res.add(cur.val);                }                if(cur.left != null){                    que.offer(cur.left);                }                if(cur.right != null){                    que.offer(cur.right);                }                size--;                            }        }        return res.get(res.size()-1);    }}

              递归

              class Solution {    private int maxDepth = Integer.MIN_VALUE;    private int result;    public int findBottomLeftValue(TreeNode root) {        if(root.left == null && root.right == null){            return root.val;        }        traversal(root,1);        return result;    }    //递归+回溯  前序遍历,因为优先向左遍历    public void traversal(TreeNode node,int depth){        //确定递归的终止条件        if(node.left == null && node.right == null){            if(depth > maxDepth){                maxDepth = depth;                result = node.val;            }            return;        }        if(node.left != null){            depth++;            traversal(node.left,depth);            depth--;        }        if(node.right != null){            depth++;            traversal(node.right,depth);            depth--;        }    }}

              1.4 总结

              递归+回溯的思路比较难,后序还需要加强掌握。

              二、力扣112.路径总和

              2.1 题目

              2.2 思路

              自己的思路:感觉和二叉树的所有路径那道题的思路一样!递归+回溯。

              本题思路:不需要像求所有路径那道题一样把所有路径都求出来,因为本题只是问是否存在这样的一条路径,所以当我们发现了这样的一条路径时,直接返回即可,不需要再遍历了。

              2.3 代码

              自己的思路(代码提交不通过,已解决)

              注意:Java集合中存储的是引用类型的数据,所以当集合中要再存入一个集合时,每次要new一个新的集合,不能多次add同一个集合(比如result里add路径集合path3次,这样会造成此时数组中就有三个相同的地址,地址相同,指向的对象自然也相同,所以此刻List集合中的三个对象其实都是指向了同一个path,而且值均为最新的赋值。)

              出问题的代码:

              class Solution {    public boolean hasPathSum(TreeNode root, int targetSum) {        List path = new ArrayList();        List res = new ArrayList();        if(root == null){            return false;        }         traversal(root,path,res);         for(int i =0;i             List                 sum += p.get(j);             }             if(sum == targetSum){                 return true;             }         }         return false;    }    //前序遍历  递归+回溯    public void traversal(TreeNode node,List        path.add(node.val);        //确定终止条件        if(node.left == null && node.right == null){            res.add(path);//!!!!!!这里的问题!!!!!!!            return;        }        //前序遍历        if(node.left != null){            traversal(node.left,path,res);            path.remove(path.size()-1);        }        if(node.right != null){            traversal(node.right,path,res);            path.remove(path.size()-1);        }    }}    public boolean hasPathSum(TreeNode root, int targetSum) {        List            return false;        }         traversal(root,path,res);         for(int i =0;i             List                 sum += p.get(j);             }             if(sum == targetSum){                 return true;             }         }         return false;    }    //前序遍历  递归+回溯    public void traversal(TreeNode node,List        path.add(node.val);        //确定终止条件        if(node.left == null && node.right == null){            res.add(new ArrayList            traversal(node.left,path,res);            path.remove(path.size()-1);        }        if(node.right != null){            traversal(node.right,path,res);            path.remove(path.size()-1);        }    }}    public boolean hasPathSum(TreeNode root, int targetSum) {        if(root == null){            return false;        }        return traversal(root,targetSum);    }    //递归+回溯  前序遍历    public boolean traversal(TreeNode node,int count){        count -= node.val;        //确定终止条件        if(node.left == null && node.right == null && count == 0){            return true;        }        if(node.left == null && node.right == null && count != 0){            return false;        }        //前序遍历        if(node.left != null){           boolean b =  traversal(node.left,count);           if(b){               return true;           }        }        if(node.right != null){           boolean a =  traversal(node.right,count);           if(a){               return true;           }        }        return false;    }}    public List        List            return res;        }        traversal(root,path,res,targetSum);        return res;    }    //递归 前序遍历 与上题不同的是找出所有,所以必须遍历整棵树    public void traversal(TreeNode node,List        count -= node.val;        path.add(node.val);        //确定终止条件,叶子结点        if(node.left == null && node.right == null && count == 0){            res.add(new ArrayList            return;        }        //前序遍历        if(node.left != null){            traversal(node.left,path,res,count);            path.remove(path.size()-1);//回溯        }        if(node.right != null){            traversal(node.right,path,res,count);            path.remove(path.size()-1);//回溯        }    }}    //利用hashmap保存中序数组数值及其下标,方便查询    public Map        hashmap =  new HashMap            hashmap.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 = hashmap.get(postorder[postEnd-1]);        TreeNode root = new TreeNode(inorder[rootIndex]);        //中序数组根节点左边的元素个数        int inLeftLength = rootIndex - inBegin;        root.left = findNode(inorder,inBegin,inBegin+inLeftLength,postorder,postBegin,postBegin+inLeftLength);        root.right = findNode(inorder,rootIndex+1,inEnd,postorder,postBegin+inLeftLength,postEnd-1);        return root;    }}    public Map        //类似于从后序与中序遍历序列构造二叉树        hashmap = new HashMap            hashmap.put(inorder[i],i);        }        return findNode(preorder,0,preorder.length-1,inorder,0,inorder.length-1);        }    //区间保持左闭右闭    public TreeNode findNode(int[] preorder,int preBegin,int preEnd,int[] inorder,int inBegin,int inEnd){        if(preBegin  preEnd || inBegin  inEnd){            return null;        }         int rootIndex = hashmap.get(preorder[preBegin]);         TreeNode root = new TreeNode(inorder[rootIndex]);         int inLeftLength = rootIndex - inBegin;         root.left = findNode(preorder,preBegin+1,preBegin+inLeftLength,inorder,inBegin,rootIndex-1);         root.right =findNode(preorder,preBegin+inLeftLength+1,preEnd,inorder,rootIndex+1,inEnd);         return root;    }}

上一篇:拍摄出色音效秘籍,专业技巧与实操指南!

下一篇:跳蚤咬痕识别指南,一眼识破,轻松应对!