代码随想录算法训练营day18 | 513.找树左下角的值,112. 路径总和 113.路径总和ii,106.从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树
513.找树左下角的值
解法一:层序遍历(简单)
class Solution {
public int findBottomLeftValue(TreeNode root) {
Deque<TreeNode> que = new LinkedList<>();
int levelSize=0;
int result=0;
if(root!=null){
que.offerFirst(root);
}
while(!que.isEmpty()){
levelSize=que.size();
result = que.peekLast().val;
while(levelSize>0){
TreeNode node = que.pollLast();
levelSize--;
if(node.left!=null)que.offerFirst(node.left);
if(node.right!=null)que.offerFirst(node.right);
}
}
return result;
}
}
解法二:递归(高效)
class Solution {
int maxDepth=0;//记录最大深度
int result=0;//装载最底层左侧叶子节点的值
public int findBottomLeftValue(TreeNode root) {
//二叉树中至少有一个节点,不用判断空值
traversal(root,1);
return result;
}
//node为当前中间节点,depth为该中间节点深度
public void traversal(TreeNode node,int depth){
if(node.left==null && node.right==null){//判断为子节点
if(depth>maxDepth){//判断为最底层最左侧节点
result=node.val;
maxDepth=depth;
return;
}
}
if(node.left!=null){
depth++;
traversal(node.left,depth);
depth--;
}
if(node.right!=null){
depth++;
traversal(node.right,depth);
depth--;
}
}
}
112. 路径总和 113.路径总和ii(有回溯,多看看)
解法一:递归法
112. 路径总和
// 112. 路径总和
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if(root==null){
return false;
}
// 单个节点判断是否符合
if (root.left == null && root.right == null) return root.val == targetSum;
targetSum -= root.val;
return traversal(root,targetSum);
}
public boolean traversal(TreeNode node,int targetSum){
if(node.left==null && node.right==null){
if(targetSum==0){
return true;
}else{
return false;
}
}
if(node.left!=null){
targetSum-=node.left.val;
if(traversal(node.left,targetSum))return true;
targetSum+=node.left.val;
}
if(node.right!=null){
targetSum-=node.right.val;
if(traversal(node.right,targetSum))return true;
targetSum+=node.right.val;
}
return false;
}
}
113.路径总和ii
// 113.路径总和ii
class Solution {
public List<List<Integer>> result = new ArrayList<>();
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
if(root!=null){
traversal(root, new ArrayList<>(), targetSum);
}
return result;
}
public void traversal(TreeNode node, List<Integer> path,int targetSum){
path.add(node.val);
// 遇到叶子节点
if(node.left==null && node.right==null){
if(targetSum-node.val==0){//路径节点之和等于目标和
result.add(new ArrayList<>(path));
}
return;
}
if(node.left!=null){
targetSum-=node.val;
traversal(node.left, path, targetSum);
targetSum+=node.val;
path.remove(path.size()-1);
}
if(node.right!=null){
targetSum-=node.val;
traversal(node.right, path, targetSum);
targetSum+=node.val;
path.remove(path.size()-1);
}
}
}
解法二:迭代法(暂不实现)
在这里插入代码片
106.从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树
教程视频:https://www.bilibili.com/video/BV1vW4y1i7dn/?vd_source=ddffd51aa532d23e6feac69924e20891
解法一:递归
106. 从中序与后序遍历序列构造二叉树
https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/
因为构造二叉树从根节点开始赋值,所以递归返回值为根结点。
递归参数是后序遍历数组和中序遍历数组。
//106. 从中序与后序遍历序列构造二叉树
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
return traversal(inorder, postorder);
}
public TreeNode traversal(int[] inorder, int[] postorder){
if(postorder.length==0)return null;
int value = postorder[postorder.length-1];
TreeNode root = new TreeNode(value);
int index;
for(index=0; index<inorder.length;index++){
if(inorder[index]==value){
break;
}
}
int[] leftInorder = java.util.Arrays.copyOf(inorder,index);
int[] rightInorder = new int[inorder.length-index-1];
System.arraycopy(inorder, index+1, rightInorder, 0, inorder.length-index-1);
int[] leftPostorder = java.util.Arrays.copyOf(postorder,leftInorder.length);
int[] rightPostorder = new int[rightInorder.length];
System.arraycopy(postorder, index, rightPostorder, 0, rightInorder.length);
root.left = traversal(leftInorder, leftPostorder);
root.right = traversal(rightInorder, rightPostorder);
return root;
}
}
105. 从前序与中序遍历序列构造二叉树
https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/
//105. 从前序与中序遍历序列构造二叉树
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
if(preorder.length==0)return null;
int value = preorder[0];
TreeNode root = new TreeNode(value);
int index;
for(index=0;index<inorder.length;index++){
if(inorder[index]==value)break;
}
int[] leftInorder = java.util.Arrays.copyOf(inorder,index);
int[] rightInorder = new int[inorder.length-index-1];
System.arraycopy(inorder, index+1, rightInorder, 0, rightInorder.length);
int[] leftPreOrder = new int[index];
System.arraycopy(preorder, 1, leftPreOrder, 0,index);
int[] rightPreOrder = new int[rightInorder.length];
System.arraycopy(preorder, index+1, rightPreOrder, 0,rightPreOrder.length);
root.left = buildTree(leftPreOrder,leftInorder);
root.right = buildTree(rightPreOrder,rightInorder);
return root;
}
}
总结
- 【513.找树左下角的值】:第一反应应该就是使用层序遍历求解,但是使用dfs求解的做法也是很不错的,记录最深的深度以及val,中序遍历在depth大于maxdepth是进行更新即可
- 【112. 路径总和 113.路径总和ii】:递归查找,每次target减少节点值,进行回溯搜索
- 【106.从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树】:利用后序确定根节点,将中序分为左右子树,再逐步处理每一个区间(注意java.util.Arrays.copyOf()方法的使用和System.arraycopy()方法的使用)