513.找树左下角的值
- 513.找树左下角的值 | 题目链接
- 代码随想录 | 讲解链接
- 题意:给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。
- 思路:递归。找到深度最深的那一条路径,返回这条路径上的叶子几点即可。那么在递归时就要计算深度depth,并且通过回溯,计算每一条路的depth。
- 递归函数的参数和返回值:参数为根节点root,用int类型的depth记录深度。不需要返回值,返回类型为void。
- 确定终止条件:当遇到叶子节点时(一个节点的左右节点都为null),就更新此时的最大深度。
- 确定单层递归的逻辑:前序遍历。遇见中间节点就统计深度,遇见左右孩子节点就递归遍历往下走,传入深度为depth+1
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
//记录最大深度
int maxDepth = 0;
//记录最大深度路径的叶子节点的值
int value = 0;
public int findBottomLeftValue(TreeNode root) {
value = root.val;
findDepthValue(root, 0);
return value;
}
public void findDepthValue(TreeNode root, int depth) {
//如果根节点为null,就结束递归
if(root == null) {
return;
}
//如果节点的左右孩子都是空,那此节点就是这条路径的叶子节点,比较这条路径的深度和最大深度,及时更新最大深度的值
if(root.left == null && root.right == null) {
if(depth > maxDepth) {
maxDepth = depth;
value = root.val;
}
}
//如果节点的左右孩子不为空,就继续递归遍历
if(root.left != null) {
findDepthValue(root.left, depth + 1);
}
if(root.right != null) {
findDepthValue(root.right, depth + 1);
}
}
}
112.路径总和
- 112.路径总和 | 题目链接
- 代码随想录 | 讲解链接
- 题意:给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。
- 思路
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
//剪枝,如果是空树,就直接返回false
if(root == null) {
return false;
}
targetSum -= root.val;
if(root.left == null && root.right == null) {
return targetSum == 0;
}
if(root.left != null) {
//看左孩子的孩子是否有满足题意的路径,有就一路往上返回true
if(hasPathSum(root.left,targetSum)) {
return true;
}
}
if(root.right != null) {
if(hasPathSum(root.right, targetSum)) {
return true;
}
}
return false;
}
}
113.路径总和Ⅱ
- 113.路径总和Ⅱ | 题目链接
- 代码随想录 | 讲解链接
- 题意:
给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
//存放结果
List<List<Integer>> res = new ArrayList<>();
//非空判断
if(root == null) {
return res;
}
//存放每条符合条件的路径
List<Integer> path = new LinkedList<>();
preorderfs(root, targetSum, res, path);
return res;
}
public void preorderfs(TreeNode root, int targetSum, List<List<Integer>> res,
List<Integer> path) {
//把此时的根节点放到路径里
path.add(root.val);
//遇到叶子节点,判断此时的targetsum-节点是否为0
if(root.left == null && root.right == null) {
if(targetSum - root.val == 0) {
//如果为0,这条path符合条件,把path加入到res中
res.add(new ArrayList<>(path));
}
return;
}
if(root.left != null) {
//传入左孩子,tagetsum减去根节点的值
preorderfs(root.left, targetSum - root.val, res, path);
//回溯,删除path中最后一个元素
path.remove(path.size() - 1);
}
if(root.right != null) {
preorderfs(root.right, targetSum - root.val, res, path);
path.remove(path.size() - 1);
}
}
}
106.从中序与后序遍历序列构造二叉树
- 106.从中序与后序遍历序列构造二叉树 | 题目链接
- 代码随想录| 讲解链接
- 题意:根据一棵树的中序遍历与后序遍历构造二叉树。注意: 你可以假设树中没有重复的元素。
- 思路
- 通过后序:找到中间节点
- 通过中序:找到中间节点后,分割中序数组以划分左右区间的元素
- 根据中序切割出的左右区间元素,再切割对应的后序数组。
- 递归处理左区间和右区间。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
//方便根据数值查找位置
Map<Integer, Integer> map;
public TreeNode buildTree(int[] inorder, int[] postorder) {
map = new HashMap<>();
//把中序存到map中便于查询位置
for(int i = 0; i < inorder.length; i++) {
map.put(inorder[i], i);
}
return finNode(inorder, 0, inorder.length, postorder, 0, postorder.length);
}
public TreeNode finNode(int[] inorder, int inBegin, int inEnd,
int[] postorder, int postBegin, int postEnd) {
//不满足左闭右开就结束
if(inBegin >= inEnd || postBegin >= postEnd) {
return null;
}
//每一棵树根节点就是后序数组的最后一个元素也就是postdorder[postEnd-1].
//根据后序遍历获取根节点后,在前序遍历中找到根节点,以此为界限分割左右孩子
//map中存放的就是前序遍历的值和索引,map.get(根节点)就是查到根节点在前序遍历中的位置
int rootIndex = map.get(postorder[postEnd - 1]);
//构造二叉树的根节点
TreeNode root = new TreeNode(inorder[rootIndex]);
//根据根节点的位置,把中序数组划分为左右子树两部分。
//左子树是左闭右开,长度就是根节点的索引 - 开始节点的索引
int lenOfLeft = rootIndex - inBegin;
//递归划分子树
//划分左子树,传入的inorder还是原先的,但根据inBein和inEnd的值的改变
//从前序数组中划分左子树,inBegin还是原来的,但是结束的范围已经变为根节点的索引值,由于是左闭右开,所以可以写到根节点的索引值。在根节点之前都是左子树
//再划分后序遍历,传入的还是后序数组
root.left = finNode(inorder, inBegin, rootIndex, postorder, postBegin, postBegin + lenOfLeft);
//根节点的右子树,就是划分的前序数组的后半部分,索引从rootIndex + 1开始到inEnd。
//划分后序数组中的右子树,就是postBegin + 左子树的长度,到后续数组长度 - 1.
root.right = finNode(inorder, rootIndex + 1, inEnd, postorder, postBegin + lenOfLeft, postEnd - 1 );
return root;
}
}
105.从前序与中序遍历序列构造二叉树
- 105.从前序与中序遍历序列构造二叉树 | 题目链接
- 思路和讲解同106:理清思路,会根据根节点在前序和中序遍历数组中划分左右子树
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
Map<Integer, Integer> map;
public TreeNode buildTree(int[] preorder, int[] inorder) {
map = new HashMap<>();
for(int i = 0; i < inorder.length; i++) {
map.put(inorder[i], i);
}
return finNode(preorder, 0, preorder.length, inorder, 0, inorder.length);
}
public TreeNode finNode(int[] preorder, int preBegin, int preEnd, int[] inorder, int inBegin, int inEnd) {
if(preBegin >= preEnd || inBegin >= inEnd) {
return null;
}
int rootIndex = map.get(preorder[preBegin]);
TreeNode root = new TreeNode(inorder[rootIndex]);
int lenOfleft = rootIndex - inBegin;
root.left = finNode(preorder, preBegin + 1, preBegin + 1 + lenOfleft, inorder, inBegin, rootIndex);
root.right = finNode(preorder, preBegin + lenOfleft + 1, preEnd, inorder, rootIndex + 1, inEnd);
return root;
}
}