Day 16 二叉树part04
513. 找树左下角的值
这道题与199. 二叉树的右视图的思路是相同的。也就可以分为递归和迭代两种方式,对于这两道题来说,迭代就是使用层序遍历的方式找到最左或最右的值即可。513这题不同的一点是,只需要找到最底层最左侧的值,而不需每一层都保存。因此考虑使用一个a_depth存储目前找到最深的结果的深度,只有找到更深的才去更新结果。
class Solution {
int ans;
int a_depth;
public int findBottomLeftValue(TreeNode root) {
findValue(root, 1);
return ans;
}
public void findValue(TreeNode cur, int depth){
if(cur == null) return;
if(depth > a_depth) {
a_depth = depth;
ans = cur.val;
}
findValue(cur.left, depth + 1);
findValue(cur.right, depth + 1);
}
}
112. 路径总和
我自己的方法和257.二叉树的所有路径 做法一致,通过使用一个列表path存储从root到当前节点的路径上所有节点,如果当前节点是叶子节点再判断其和是否等于targetsum即可。很明显,这个path是没有必要存储的,官解的代码放在下面了,反正就是优雅,优雅。
class Solution { //自己写的丑陋版本,比较类似于二叉树所有路径那道题,但我这样的做法相当于复杂化了,许多东西并不需要存储。但这种做法对于路径总和Ⅱ是必要的。
public boolean hasPathSum(TreeNode root, int targetSum) {
if(root == null) return false;
List<Integer> path = new ArrayList();
return findPath(root, path, targetSum);
}
public boolean findPath(TreeNode cur, List<Integer> path, int targetSum){
if(cur != null) path.add(cur.val);
if(cur.left == null && cur.right == null && sum(path) == targetSum) return true;
if(cur.left != null){
if(findPath(cur.left, path, targetSum)) return true;
path.remove(path.size()-1);
}
if(cur.right != null){
if(findPath(cur.right, path, targetSum)) return true;
path.remove(path.size() - 1);
}
return false;
}
public int sum(List<Integer> path){
int ans = 0;
for(Integer i : path) ans += i;
return ans;
}
}
class Solution { // 官解
public boolean hasPathSum(TreeNode root, int targetSum) {
if(root == null) return false;
if(root.left == null && root.right == null && root.val == targetSum) return true;
return hasPathSum(root.left, targetSum - root.val) ||
hasPathSum(root.right, targetSum - root.val);
}
}
113. 路径总和 II
会了上一题再做这个就会容易不少
class Solution {
List<List<Integer>> res = new ArrayList();
List<Integer> path = new ArrayList();
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
getPaths(root, targetSum);
return res;
}
public void getPaths(TreeNode root, int targetSum){
if(root == null) return;
path.add(root.val);
if(root.val == targetSum && root.left == null && root.right == null){
res.add(new ArrayList(path));
}
if(root.left != null){
getPaths(root.left, targetSum - root.val);
path.remove(path.size() - 1); //回溯path
}
if(root.right != null){
getPaths(root.right, targetSum - root.val);
path.remove(path.size() - 1); // 回溯path
}
}
}
106. 从中序与后序遍历序列构造二叉树
居然自己没看题解就写出来了,哈哈哈哈虽然花的时间很多。主要就是要理清中序和后序遍历的关系。可以知道,后序遍历的最后一个节点,一定是根节点,找到这个根节点后,再去中序遍历中,用它进行分割,就能找到对于该根节点左子树的节点集合和右子树的节点集合。同样的,中序遍历中左子树中节点集合的长度与后序遍历中左子树中节点集合的长度相同,因此只需要去分割左右子树的节点集合出来用于递归的解决左子树和右子树的问题。
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
if(inorder.length == 0) return null;
int mid = postorder[inorder.length-1]; //后序遍历的最后一个节点为根节点
int ind = -1;
for(int i = 0; i < inorder.length; i++){
if(inorder[i] == mid) {ind = i; break;} // 找根节点的index
}
TreeNode left = buildTree(Arrays.copyOfRange(inorder, 0, ind), Arrays.copyOfRange(postorder, 0, ind)); //函数参数为 左子树的中序遍历,左子树的后序遍历
TreeNode right = buildTree(Arrays.copyOfRange(inorder, ind + 1, inorder.length),
Arrays.copyOfRange(postorder, ind, postorder.length-1));
//函数参数为 右子树的中序遍历,右子树的后序遍历
TreeNode cur = new TreeNode(mid, left, right); //左右子树构建好后,跟根节点构成完整的树
return cur;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步