代码随想录算法训练营第十八天|513.找树左下角的值、112.路径总和、113.路径总和II、106.从中序与后序遍历构造二叉树、105.从前序与中序遍历构造二叉树
513.找树左下角的值
给定一个二叉树的 根节点 root
,请找出该二叉树的 最底层 最左边 节点的值。
假设二叉树中至少有一个节点。
示例 1:
输入: root = [2,1,3]
输出: 1
题解:看清楚题目!!是树的最后一行最左边的节点,不是树的最左的左节点,也就是说这个节点可以是右节点。
代码:
递归解法:如果节点是叶子节点,判断当前深度是不是最大深度,是的话就保存该节点的值,然后更新深度,不是则不更新值和深度。
class Solution {
int deeps=-1;
int value=0;
public int findBottomLeftValue(TreeNode root) {
if(root==null) return 0;
digui(root,0);
return value;
}
public void digui(TreeNode node,int deep){
if(node==null) return ;
if(node.left==null && node.right==null){
if(deep>deeps){
value=node.val;
deeps=deep;
}
}
digui(node.left,deep+1);
digui(node.right,deep+1);
}
}
迭代解法:层序遍历,最后一个节点的值就是需要的值。
class Solution {
public int findBottomLeftValue(TreeNode root) {
if(root==null) return 0;
Queue<TreeNode> que=new LinkedList<>();
que.offer(root);
int res=0;
while(!que.isEmpty()){
int len=que.size();
for(int i=0;i<len;i++){
TreeNode node=que.poll();
if(i==0) res=node.val;
if(node.left!=null) que.offer(node.left);
if(node.right!=null) que.offer(node.right);
}
}
return res;
}
}
112.路径总和
给你二叉树的根节点 root
和一个表示目标和的整数 targetSum
。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum
。如果存在,返回 true
;否则,返回 false
。
叶子节点 是指没有子节点的节点。
示例 1:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。
题解:递归解决这个题。从跟节点开始,每到要遍历到下一个节点,要减去当前节点的值,减到最后一个节点,如果目标值减去的值和叶子节点的值相等,说明这是一条可行的道路。需要注意的是,最后的判断条件,target不是等于0,而是看是否等于最后一个叶子节点。
代码:
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if(root==null) return false;
if(root.left==null && root.right==null && targetSum==root.val){
return true;
}
if(root.left!=null){
boolean flag=hasPathSum(root.left,targetSum-root.val);
if(flag) return true;
}
if(root.right!=null){
boolean flag=hasPathSum(root.right,targetSum-root.val);
if(flag) return true;
}
return false;
}
}
113.路径总和II
给你二叉树的根节点 root
和一个整数目标和 targetSum
,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
叶子节点 是指没有子节点的节点。
示例 1:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:[[5,4,11,2],[5,8,4,5]]
题解:该怎么保存经过的路径呢?用LIst保存经过的节点的值,然后再将list添加到LIst<List>中。需要注意的是,在添加到最后的结果数组时,添加的需要时list的备份,不然会改变list里面的值,影响下一条路径节点值的保存。
//不是很好的方法,new ArrayList<>(list)相当于给每个节点都新建了一个对象,但是代码便于理解。
代码:
class Solution {
List<List<Integer>> res=new ArrayList<>();
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
List<Integer> list=new ArrayList<>();
digui(root,targetSum,list);
return res;
}
public void digui(TreeNode node,int targetSum,List<Integer> list){
if(node==null) return;
list.add(node.val);
//满足条件,加入路径
if(node.left==null && node.right==null && node.val==targetSum){
res.add(new ArrayList<>(list));
}
if(node.left!=null){
digui(node.left,targetSum-node.val,new ArrayList<>(list));
}
if(node.right!=null){
digui(node.right,targetSum-node.val,new ArrayList<>(list));
}
}
}
106.从中序与后序遍历构造二叉树
给定两个整数数组 inorder
和 postorder
,其中 inorder
是二叉树的中序遍历, postorder
是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
示例 1:
输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
输出:[3,9,20,null,null,15,7]
题解:后序和中序构造二叉树的步骤:
- 后序数组为空,空节点
- 后序数组的最后一个元素是根节点
- 寻找中序数组位置的切割点
- 切中序数组
- 切后序数组
- 递归处理左区间后区间
代码:
class Solution {
Map<Integer,Integer> map=new HashMap<>();
public TreeNode buildTree(int[] in, int[] po) {
for(int i=0;i<in.length;i++){ //保存前序的节点,便于分割
map.put(in[i],i);
}
return getNode(in,0,in.length,po,0,po.length);
}
//递归实现分割过程
public TreeNode getNode(int[] in,int inbegin,int inend,int [] po,int pobegin,int poend){
if(inbegin>=inend || pobegin>=poend) return null;
//这里需要注意,中间节点的改变
int rootIndex=map.get(po[poend-1]);
TreeNode root=new TreeNode(in[rootIndex]);
int llen=rootIndex-inbegin;
root.left=getNode(in,inbegin,rootIndex,po,pobegin,pobegin+llen);
root.right=getNode(in,rootIndex+1,inend,po,pobegin+llen,poend-1);
return root;
}
}
105.从前序与中序遍历构造二叉树
给定两个整数数组 preorder
和 inorder
,其中 preorder
是二叉树的先序遍历, inorder
是同一棵树的中序遍历,请构造二叉树并返回其根节点。
示例 1:
输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]
题解:和上一个题相比,有一个问题:pre的开始节点要怎么确定呢,第一个当然是0,第二个是加上len后的位置,但是len 又得在开始节点后面才能确定,所以要怎么解决这个问题呢?方法很简单,在传入参数的时候,参数加一就可以了。
代码:
class Solution {
Map<Integer,Integer> map=new HashMap<>();
public TreeNode buildTree(int[] pre, int[] in) {
//把中序数组放进map
for(int i=0;i<in.length;i++){
map.put(in[i],i);
}
return getNode(pre,0,pre.length,in,0,in.length);
}
public TreeNode getNode(int [] pre,int preb,int pree,int[] in,int inb,int ine){
if(inb>=ine || preb>=pree) return null;
int rootIndex=map.get(pre[preb]);
TreeNode root=new TreeNode(in[rootIndex]);
int llen=rootIndex-inb;
root.left=getNode(pre,preb+1,preb+llen+1,in,inb,rootIndex);
root.right=getNode(pre,preb+llen+1,pree,in,rootIndex+1,ine);
return root;
}
}