一)计算布尔二叉树的值
2331. 计算布尔二叉树的值 - 力扣(LeetCode)
1)计算布尔二叉树需要从叶子节点向上进行计算,从下向上进行计算
2)完整二叉树是同时拥有左孩子和右孩子,或者是完全没有右孩子
3)当我只是盯着根节点来看的时候,此时我想知道我这一层的结果是什么?必须先知道这个根节点的左子树的布尔值,还需要知道右子树的布尔值,当我知道左右子树是true或者是false的时候,在我这一层把左右子树的信息整合;
4)如果想要知道左子树或者是右子树是true还是false,这不是恰好和我们的大问题是一样的吗?主问题就是解决这棵树是true还是false
5)重复子问题函数头:给定一个指针,判断以这个指针为结点的树是true还是false,求以这个节点为根节点的boolean值
6)函数体:先知道左子树是true还是false,再知道右子树是true还是false最后在本层进行整合
boolean flag1=dfs(root.left);
boolean flag2=dfs(root.right);
return root.val==2?flag1orflag2:flag1&flag2
7)递归出口:遇到叶子节点,只需要将叶子节点是true还是false返回
8)本质上这个题就是在做一个后序遍历,本质上就是一个深度优先遍历,先返回左节点的boolean值,再返回右节点的boolean值,最后再根据根结点的值进行计算,在遇到叶子节点的时候,将叶子节点的信息返回到上一层
class Solution { public boolean evaluateTree(TreeNode root) { if(root==null) return true; if(root.left==null&&root.right==null) return root.val==0?false:true; //先进行计算左子树的boolean值 boolean flag1=evaluateTree(root.left); //再进行计算右子树的boolean boolean flag2=evaluateTree(root.right); return root.val==2?flag1|flag2:flag1&flag2; } }
二)求根节点到叶子节点数字之和
129. 求根节点到叶节点数字之和 - 力扣(LeetCode)
1)二叉树的递归问题想一下递归到某一层的时候要干什么事情,当遍历到某一个根节点所干的事情都一样的时候,况且干这个事情能够得到最终我所想要的结果,那么这个这个事情就是相同子问题,当我们遍历到某一个根节点的时候,还是需要将这个跟跟节点的左子树之和和右子树之和计算相加返回给上一层
2)此时我们需要进行计算的点就是当遍历到某一个根节点的时候,需要知道前面的数字的信息,就比如说遍历到5的时候是需要知道12的信息的,因为当前我遍历到这一层的时候我什么也不知道,我怎么计算出1258呢?我只是知道当前根节点以及后续节点的信息,根本不知道当前根节点以前的信息
3)知道12的信息之后,再结合当前根节点进行计算出125的值,然后再将125传递给它的左子树和右子树,算出左右子树的值,最后将对应的值返回给根节点,在进行相加,返回到上一层节点
第一步:知道前面的数是12之后,进行计算当前结点的值是125
第二步:将当前的这个125传递给以5为根节点的左子树,算出左子树的和是1258
第三步:将这个125传递给以5为根节点的右子树,计算出右子树的和是XXXX
第四步:将左子树和右子树返回的和进行相加,最后返回当前根节点的上一层
1)函数头的设计:你给我传入一个根节点之后,把以这个根节点相连的左右子树叶子之和进行返回,int dfs(Node root,int k)参数是当前传入的根节点和你传递到这个根节点的时候,从原始根节点到这个递归层次的结点的路径和,传入一个根节点,计算出以当前根节点的所有叶子节点之和进行返回
2)函数体:执行1 2 3 4步
3)递归出口:递归出口是在第二步进行执行的
class Solution { public int GetSum(TreeNode root,int k){ //根据题目给定的数据范围来说不可能出现根节点的情况 //遍历到叶子结点的时候才到了递归结束的出口 if(root.left==null&&root.right==null){ return root.val+k*10; } int current=k*10+root.val; int ret=0; //算出左子树的和 if(root.left!=null) ret+=GetSum(root.left,current); //算出右子树的和 if(root.right!=null) ret+=GetSum(root.right,current); //返回值是左子树和右子树的和 return ret; } public int sumNumbers(TreeNode root) { return GetSum(root,0); } }
三)二叉树剪枝:
814. 二叉树剪枝 - 力扣(LeetCode)
1)在这个问题中子问题就是给定一个头指针,将以这个头指针为根节点的所有为0的子树全部干掉,返回最后处理结果的头指针
2)当给定一个头结点的信息的时候,我必须知道以当前根节点的左子树的信息和以当前根节点的右子树的信息,必须是左子树全为0或者是右子树全为0,我才可以将左子树或者是右子树剪掉,所以需要后序遍历,因为只有出现后序遍历的时候,才能带着左子树的信息和右子树的信息;
3)进行模拟递归的过程:从叶子节点开始判断,通过决策树模拟删除递归的这样一个过程即可
1)当判断完左子树之后,我需要继续进行判断右子树也就是0的右节点,此时发现右节点的左子树和右子树也都是空,况且右节点的值也是0,所以右节点也是可以干掉的,但是此时返回到1的时候虽然发现左节点和右节点都是空,但是发现当前根节点是1,所以不能干掉
2)接下来继续判断0的右节点
3)函数体:先处理左子树,再进行处理右子树,再来处理当前节点
4)函数出口:root=null
class Solution { //给定一个根节点,返回左子树和右子树简直之后的头节点 public TreeNode pruneTree(TreeNode root) { if(root==null) return null; root.left=pruneTree(root.left); //返回左子树剪枝之后的结果,将左子树中是0的分支全部干掉,返回处理完成之后的左根节点 root.right=pruneTree(root.right); //返回右子树剪枝之后的结果,将右子树是的0的分支全部干掉,返回处理之后的右根节点 //判断当前位置是否需要剪枝,如果发现左右子树都为空,况且当前节点是0,那么直接返回即可 if(root.left==null&&root.right==null&&root.val==0){ return null; }else{ return root; } } }
四)验证二叉搜索树
98. 验证二叉搜索树 - 力扣(LeetCode)
之前我的做题思路就是说先进行判断一下以当前节点为根节点的左子节点和右子节点是一颗二叉搜索树,再进行判断当前根节点的左子树是否是一颗二叉搜索树,和当前根节点的右子树是否是一颗二叉搜索树没但是这个判断方法是错误的,只能通过72个测试用例,请看上面
解法1:根据中序遍历的结果来判断这颗树是否是二叉搜索树
class Solution { public List<Integer> GetList(TreeNode root){ Stack<TreeNode> stack=new Stack<>(); List<Integer> list=new ArrayList<>(); while(!stack.isEmpty()||root!=null){ while(root!=null){ stack.push(root); root=root.left; } TreeNode node=stack.pop(); list.add(node.val); root=node.right; } return list; } public boolean isValidBST(TreeNode root) { List<Integer> list=GetList(root); for(int i=0;i<list.size()-1;i++){ if(list.get(i)>=list.get(i+1)) return false; } return true; } }