左叶子之和
左叶子的明确定义:如果左节点不为空,且左节点没有左右孩子,那么这个节点的左节点就是左叶子
如果该节点的左节点不为空,该节点的左节点的左节点为空,该节点的左节点的右节点为空,则找到了一个左叶子。
完整代码如下:
递归法
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
if(root==null) return 0;
int leftValue =sumOfLeftLeaves(root.left);
int rightValue =sumOfLeftLeaves(root.right);
int midValue =0;
if(root.left!=null&&root.left.left==null&&root.left.right==null){
midValue=root.left.val;
}
int sum =leftValue+rightValue+midValue;
return sum;
}
}
找树左下角之和
该题的意识就是:在树的最后一行找到最左边的值。
两个关键点:1.最后一行
2.最左边的值
因为要找到最后一行,所以本题用迭代法中层次遍历最为方便。
完整代码如下:
迭代法
注意 if(i==0) result=node.val;
class Solution {
public int findBottomLeftValue(TreeNode root) {
if(root==null) return 0;
Queue<TreeNode> queue =new LinkedList<>();
queue.offer(root);
int result =0;
while(!queue.isEmpty()){
int size=queue.size();
for(int i=0;i<size;i++){
TreeNode node =queue.poll();
if(i==0){
result =node.val;
}
if(node.left!=null)queue.offer(node.left);
if(node.right!=null)queue.offer(node.right);
}
}
return result;
}
}
递归法:
- 确定递归函数的参数和返回值
本题需要定义两个全局变量1.记录最大深度maxLen 2.记录最大深度最左节点数值maxleftValue
参数:1.遍历的树的根节点。2.int类型的变量:记录最长深度
无返回值
如果需要遍历整棵树,递归函数就不能有返回值。如果需要遍历某一条固定路线,递归函数就一定要有返回值!
2.确定终止条件
当遇到叶子节点时,就需要统计一下最大的深度。
3.确定单层递归的逻辑
在找最大深度的时候,递归的过程中依然要使用回溯。
class Solution {
private int maxDeep=-1;
private int value=0;
public int findBottomLeftValue(TreeNode root) {
value=root.val;
findleftValue(root,0);
return value;
}
private void findleftValue(TreeNode root,int deep){
if(root==null)return ;
if(root.left==null&&root.right==null){
if(deep>maxDeep){
value =root.val;
maxDeep =deep;
}
}
if(root.left!=null){
findleftValue(root.left,deep+1);
}
if(root.right!=null){
findleftValue(root.right,deep+1);
}
}
}
路径总和
此题分为两类
(1)判断该树中是否存在根节点到叶子节点的路径
(2)找到所有从根节点到叶子节点路径总和等于给定目标和的路径
(1)
递归法
- 确定递归函数的参数和返回类型
参数:1.二叉树的根节点 2.一个计数器
返回类型 bool
2.确定终止条件
先让计数器初始值为目标值,每次减去遍历路径节点上的数值
最后count==0
3.确定单层递归的逻辑
完整代码如下:
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if(root==null) return false;
targetSum-=root.val;
if(root.left==null&&root.right==null){
return targetSum==0;
}
if(root.left!=null){
boolean left=hasPathSum(root.left,targetSum);
if(left){
return true;
}
}
if(root.right!=null){
boolean right =hasPathSum(root.right,targetSum);
if(right){
return true;
}
}
return false;
}
}
迭代法
需要定义两个栈 一个存放节点 另一个存放节点的数值
完整代码如下:
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if(root==null)return false;
Stack<TreeNode> stack1=new Stack<>();
Stack<Integer> stack2=new Stack<>();
stack1.push(root);
stack2.push(root.val);
while(!stack1.isEmpty()){
int size =stack1.size();
for(int i=0;i<size;i++){
TreeNode node=stack1.pop();
int sum =stack2.pop();
if(node.left==null&&node.right==null&&sum==targetSum){
return true;
}
if(node.left!=null){
stack1.push(node.left);
stack2.push(sum+node.left.val);
}
if(node.right!=null){
stack1.push(node.right);
stack2.push(sum+node.right.val);
}
}
}
return false;
}
}
(2)
递归法
注意:找到所有路径,递归函数不要返回值
递归方法:需要回溯 path.remove(path.size()-1);
需要创建List<List<Integer>> result =new ArrayList<>();存放结果
List<Integer> path =new LinkedList<>();存放数值
注意:数值加入到结果时需要重新创建一个数组列表 result.add(new ArrayList<>(path));
完整代码如下:
class Solution {
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
List<List<Integer>> result= new ArrayList<>();
if(root==null) {return result;}
List<Integer> path =new LinkedList<>();
preoreder(root,targetSum,result,path);
return result;
}
private void preoreder(TreeNode root,int targetSum,List<List<Integer>> result,List<Integer> path){
path.add(root.val);
if(root.left==null&&root.right==null&&targetSum==root.val){
result.add(new ArrayList<>(path));
}
if(root.left!=null){
preoreder(root.left,targetSum-root.val,result,path);
path.remove(path.size()-1);
}
if(root.right!=null){
preoreder(root.right,targetSum-root.val,result,path);
path.remove(path.size()-1);
}
}
}