二叉树刷题总结
二叉树的基础
- 满二叉树,二叉树节点满足,2的N次方-1的树
- 完全二叉树,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。
- 二叉搜索树
- 左子树不空,则左子树的每一个节点小于根节点
- 右子树不空,则右子树的每一个节点大于根节点
- 左子树与右子树都满足二叉搜索树的概念
- 平衡二叉搜索树:在二叉搜索树的技术上,增加一条,左子树右子树高度差不超过1。
二叉树的定义
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;
}
}
二叉树的遍历
二叉树的遍历可谓是二叉树的精髓中的精髓中的精髓,一定要好好理解好好把我。
二叉树的遍历方式
- 广度优先遍历
- 深度优先遍历
- 前序遍历
- 中序遍历
- 后续遍历
这五种遍历都是重要的不能再重要的遍历,一定不能背要好好理解好好琢磨。
广度遍历
在广度遍历这里,我想重点提出一句话。进入下一层遍历的时候,队列里已经没有本层的节点了。
在理解这句话之前,我的广度遍历不能分层,理解这句话后,我的广度遍历就能分层。
举个例子
LinkedList<Integer> list;
public void bfs_no_layer(TreeNode root){
list = new LinkedList<Integer>();
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
while (!queue.isEmpty()){
TreeNode poll = queue.poll();
if (poll.left != null) queue.add(poll.left);
if (poll.right != null) queue.add(poll.right);
list.add(poll.val);
}
}
public static void main(String[] args) {
TreeNode node1 = new TreeNode(1);
TreeNode node2 = new TreeNode(2);
TreeNode node3 = new TreeNode(3);
TreeNode node4 = new TreeNode(4);
TreeNode node5 = new TreeNode(5);
TreeNode node6 = new TreeNode(6);
TreeNode node7 = new TreeNode(7);
node1.left = node2;
node1.right = node3;
node2.left = node4;
node2.right = node5;
node3.right = node7;
node5.left = node6;
BFS bfs = new BFS();
bfs.bfs_no_layer(node1);
for(int i :bfs.list){
System.out.print(i+" ");
}
}
在这里也是广度遍历,但是这个广度遍历,输出的节点是没有分层的。这个是相当致命的。很多问题因此无法解决。
但是只要理解一句话进入新的一层的这个瞬间,队列里只有当前层的节点
import java.util.LinkedList;
import java.util.Queue;
public class BFS {
LinkedList<Integer> list;
LinkedList<LinkedList<Integer>> list2;
public void bfs_no_layer(TreeNode root){
list = new LinkedList<Integer>();
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
while (!queue.isEmpty()){
TreeNode poll = queue.poll();
if (poll.left != null) queue.add(poll.left);
if (poll.right != null) queue.add(poll.right);
list.add(poll.val);
}
}
public void bfs_have_layer(TreeNode root){
list2 = new LinkedList<LinkedList<Integer>>();
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
while (!queue.isEmpty()){
int size = queue.size();//抓住这个瞬间,记录下此时节点有多少个
LinkedList<Integer> templist = new LinkedList<Integer>();
while (size > 0){
size--;
TreeNode poll = queue.poll();
if (poll.left != null) queue.add(poll.left);
if (poll.right != null) queue.add(poll.right);
templist.add(poll.val);
}
list2.add(templist);
}
}
public static void main(String[] args) {
TreeNode node1 = new TreeNode(1);
TreeNode node2 = new TreeNode(2);
TreeNode node3 = new TreeNode(3);
TreeNode node4 = new TreeNode(4);
TreeNode node5 = new TreeNode(5);
TreeNode node6 = new TreeNode(6);
TreeNode node7 = new TreeNode(7);
node1.left = node2;
node1.right = node3;
node2.left = node4;
node2.right = node5;
node3.right = node7;
node5.left = node6;
BFS bfs = new BFS();
bfs.bfs_no_layer(node1);
bfs.bfs_have_layer(node1);
for(int i :bfs.list){
System.out.print(i+" ");
}
System.out.println();
for (LinkedList<Integer> list : bfs.list2){
for (int i :list){
System.out.print(i+" ");
}
System.out.println();
}
}
}
仔细理解这段代码很重要!!!
来看一些BFS的题目
leetcode 199. 二叉树的右视图
这道题和明显,分析题目,就知道要找到每一层最右边的节点。分层次的层次遍历,很轻易就可以做到。只需要在每一层遍历(第二个小循环)中,记录最后一个被遍历到的节点即可
public List<Integer> rightSideView(TreeNode root) {
List<Integer> list = new LinkedList<Integer>();
if(root == null) return list;
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
while (!queue.isEmpty()){
int size = queue.size();//抓住这个瞬间,记录下此时节点有多少个
int temp = 0;
while (size > 0){
size--;
TreeNode poll = queue.poll();
if (poll.left != null) queue.add(poll.left);
if (poll.right != null) queue.add(poll.right);
temp = poll.val; //在这里进行了改动.
}
list.add(temp);
}
return list;
}
leetcode 637 层的平均值
大同小异
public List<Double> averageOfLevels(TreeNode root) {
List<Double> list = new LinkedList<Double>();
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
while (!queue.isEmpty()){
int size = queue.size();//抓住这个瞬间,记录下此时节点有多少个
double sum = 0;
double num = 0;
while (size > 0){
size--;
TreeNode poll = queue.poll();
if (poll.left != null) queue.add(poll.left);
if (poll.right != null) queue.add(poll.right);
num++;
sum += poll.val;
}
list.add(sum/num);
}
return list;
}
同理,最大深度,就是层次遍历很简单的应用。
最小深度就是层次遍历,遇到根节点就可以退出。这么点区别。
二叉树遍历
因为层次遍历比较特殊,单独拿出来说。
二叉树的深度遍历,规定好方向其实就是变成先序遍历。两者没有本质的区别。
如何递归
在此之前,我想先表明,递归是什么操作。如何递归。在我们准备一个递归的时候需要解决以下几个问题。
- 参数:应该选择什么参数来进入迭代。
- 递归的终止条件:什么时候return
- 返回值
- 最后才是业务逻辑
二叉树的前序遍历
前序遍历的顺序:根、左子树、右子树。
LinkedList<Integer> list = new LinkedList<Integer>();
public List<Integer> preorderTraversal(TreeNode root) {
recur(root);
return list;
}
public void recur(TreeNode root){
if (root == null) return;
list.add(root.val);
recur(root.left);
recur(root.right);
}
值得注意的是,为什么要分两个函数来写。就是因为第一个函数的返回值不同。就很多考点都是在这里,就是一个前序遍历,你怎么用这个前序遍历获得你想要的东西,this is point。
给出前序遍历的递归写法。
public List<Integer> preorderTraversal(TreeNode root) {
LinkedList<Integer> res = new LinkedList<Integer>();
if (root == null) return res;
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.add(root);
while (!stack.isEmpty()){
System.out.println(1);
TreeNode poll = stack.pop();
res.add(poll.val);
if(poll.right != null) stack.add(poll.right);
if(poll.left != null) stack.add(poll.left);
}
return res;
}
很简单,因为前序遍历的顺序和代码的执行顺序是相同的,只需要先访问节点,再去放入就可以了。
二叉树的中序遍历
二叉树的中序遍历的递归手段和先序遍历没有本质上的区别,都是照猫画虎,就业务逻辑上有一点点小差别
LinkedList<Integer> list = new LinkedList<Integer>();
public List<Integer> inorderTraversal(TreeNode root) {
recur(root);
return list;
}
public void recur(TreeNode root){
if (root == null) return;
recur(root.left);
list.add(root.val);
recur(root.right);
}
需要注意的是,其实在二叉树的题目中,很多递归的终止条件有两个反复出现的点
- root == null
- root.left == null && root.right == null
二叉树的中序遍历的迭代版本。如果害按照前序遍历的逻辑去写中序遍历的迭代算法是行不通的。
public List<Integer> inorderTraversal_2(TreeNode root) {
Stack<TreeNode> stack = new Stack<TreeNode>();
LinkedList<Integer> res = new LinkedList<Integer>();
stack.add(root);
TreeNode cur = root;
while (cur!=null || !stack.isEmpty()){
if (cur == null){
//说明此时遍历到上一个是叶子结点
cur = stack.pop();
res.add(cur.val);
cur = cur.right;
}else {
stack.add(cur);
cur = cur.left;
}
}
return res;
}
在中序遍历中,我们采用了一个cur来记录当前的节点。并且在栈中保存了上一个节点。如果采用cur不等于null一直向左遍历的特点。当cur == null的时候,那上一个节点一定是当前时间最左,可以放出来进行访问。此时再记录右子树。整体是这样的逻辑。
二叉树的后续遍历
递归手段
LinkedList<Integer> list = new LinkedList<Integer>();
public List<Integer> postorderTraversal(TreeNode root) {
recur(root);
return list;
}
public void recur(TreeNode root){
if (root == null) return;
recur(root.left);
recur(root.right);
list.add(root.val);
}
但是二叉树后序遍历的递归手法真的很巧妙,对于前序遍历,我们访问的顺序是根,左子树,右子树,对于后续遍历访问的顺序是左子树,右子树,根,如果有一个访问顺序是根, 右子树,左子树,那么颠倒顺序就是后续遍历。
public List<Integer> postorderTraversal_2(TreeNode root) {
LinkedList<Integer> list = new LinkedList<Integer>();
if (root == null) return list;
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.add(root);
while (!stack.isEmpty()){
TreeNode pop = stack.pop();
list.add(pop.val);
if (pop.left != null) stack.add(pop.left);
if (pop.right != null) stack.add(pop.right);
}
Collections.reverse(list);
return list;
}
掌握了这些,接下来就可以开始愉快的刷题之旅啦
- 翻转二叉树
这道题用递归的方法做。对每一颗树都调换一下左子树和右子树
public TreeNode invertTree(TreeNode root) {
if (root == null) return null;
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
invertTree(root.right);
invertTree(root.left);
return root;
}
这道题为什么会想到递归的思路呢。我现在对于二叉树的递归思路都是从顶到下的。什么意思,就是说我先看root的left与right调换会有什么效果,再看root.left的left和right调换会有什么效果。目前对于二叉树的递归我是这么理解的。
222.完全二叉树的节点个数
public int countNodes(TreeNode root) {
if (root == null) return 0;
int num = 0;
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
while (!queue.isEmpty()){
TreeNode poll = queue.poll();
num++;
if (poll.left != null) queue.add(poll.left);
if (poll.right != null) queue.add(poll.right);
}
return num;
}
这道题的深度遍历和广度遍历我都写了。但是利用完全二叉树性质的那个方法我还没研究。
- 平衡二叉树
public boolean isBalanced(TreeNode root) {
if (root == null) return true;
int left = getDeep(root.left);
int right = getDeep(root.right);
boolean tag = false;
if (Math.abs(left - right) <= 1) tag = true;
return tag && isBalanced(root.left) && isBalanced(root.right);
}
public int getDeep(TreeNode root){
if (root == null) return 0;
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
int num_layer = 0;
while (!queue.isEmpty()){
int size = queue.size();
while (size > 0){
size--;
TreeNode poll = queue.poll();
if (poll.left != null) queue.add(poll.left);
if (poll.right != null) queue.add(poll.right);
}
num_layer++;
}
return num_layer;
}
这道题,我一开始的思路是,用层次遍历,找到最短的层和最大的层,但是后面我发现,我这个思路有一个巨大的bug,就是我只考虑到了root节点是不是平衡树,我没有考虑到子树的是不是平衡树。所以我采用了递归的手段。有没有发现,其实递归最大的好处是,能保证每一颗树(树的组成部分)是复合递归的规律的!这个是递归的核心。
257 记录二叉树所有路径
这道题我愿称之为很考验基础功的一道题
List<String> res = new LinkedList<String>();
public List<String> binaryTreePaths(TreeNode root) {
if (root == null) return res;
String str = String.valueOf(root.val);
if (root.left == null && root.right == null){
res.add(str);
return res;
}
recur(root.left,str);
recur(root.right,str);
return res;
}
public void recur(TreeNode root,String path){
if(root == null) return;
path = path + "->"+root.val;
if (root.left == null && root.right == null){
res.add(path);
return;
}
recur(root.left,path);
recur(root.right,path);
}
- 这道题的思路还是很简单的,就是一个深度遍历循环,没什么特点。
- 考验对于首个节点的把握程度。怎么去把握第一个节点是关键!对于这种第一个节点不能递归处理的,就把他放在主程序中,副程序递归左子树和右子树就可以。
- 对于终止的条件的把握,我第一次作对了,第二次做错了,就是因为对于终止条件的把我不够明确。所谓终止条件,无非就两个,root == null 和root.leftnull&&root.rightnull。在这里如何把我还是很考验人的。
404. 左叶子之和 字节算法题的面试真题
int sum = 0;
public int sumOfLeftLeaves(TreeNode root) {
if (root == null) return 0;
recur(root.left,true);
recur(root.right,false);
return sum;
}
public void recur(TreeNode root,boolean tag){
//在recur中要做的很简单
//1.判断是不是叶子结点
//2.判断是不是左节点
if (root == null) return;
if (root.left == null && root.right ==null){
if (tag) sum += root.val;
}
recur(root.left,true);
recur(root.right,false);
}
这这道题里面,每一次迭代遍历需要做两件事
- 判断这个节点是不是叶子节点
- 判断这个节点是不是左节点。在这里判断是不是左节点,我用了一个tag来做辅助。
值得注意的是,在这里我用了两个终止条件,之所以这么做可以节省一些些代码。
513.找树左下角的值
也不知道这道题为什么就是中等难度的了= - =我觉得还挺简单啊。
public int findBottomLeftValue(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
LinkedList<Integer> list = null;
while (!queue.isEmpty()){
list = new LinkedList<Integer>();
int size = queue.size();
while (size >0){
size--;
TreeNode poll = queue.poll();
list.add(poll.val);
if(poll.left != null) queue.add(poll.left);
if(poll.right != null) queue.add(poll.right);
}
}
return list.get(0);
}
112.路径总和
这道题还是考验基础是不是扎实。本质上就是一个深度循环遍历。我采用了两种方式来写
第一种,不额外增加空间.
public boolean hasPathSum(TreeNode root, int targetSum) {
if (root == null) return false;
if (root.left == null && root.right == null){
if (root.val == targetSum) return true;
else return false;
}
return recur(root,targetSum,0);
}
public boolean recur(TreeNode root,int targetSum,int path){
path += root.val;
if (root.left == null && root.right ==null){
if (path == targetSum) return true;
else return false;
}
boolean tag1 = false;
boolean tag2 = false;
if (root.left != null) tag1 = recur(root.left,targetSum,path);
if (root.right != null) tag2 = recur(root.right,targetSum,path);
return tag1 || tag2;
}
第二种,增加了一个list来记录路径之和
List<Integer> list = new LinkedList<Integer>();
public boolean hasPathSum(TreeNode root, int targetSum) {
if(root == null) return false;
recure(root,0);
for (int i : list){
if (i == targetSum)
return true;
}
return false;
}
public void recure(TreeNode root,int path){
if (root.right == null && root.left == null){
path += root.val;
list.add(path);
return;
}
path = path + root.val;
if (root.left != null) recure(root.left,path);
if (root.right != null) recure(root.right,path);
}
105 从前序与中序遍历序列构造二叉树
这道题有两个难点
难点1. 逻辑不是特别好理解
难点2. 理解了逻辑之后,怎么表达出来
明确1. 前序遍历和后续遍历可以帮助我们找到根,中序遍历可以帮助我们划分左子树和右子树。
剩下的就是如何去处理。
HashMap<Integer,Integer> map;
public TreeNode buildTree(int[] preorder, int[] inorder) {
//明确,前序找根,中序划分左子树和右子树
map = new HashMap<Integer, Integer>();
int count = 0;
for (int i : inorder) map.put(i,count++);
//定义一个map帮助我们来划分左子树和右子树
return recur(preorder,inorder,0,preorder.length-1,0,inorder.length-1);
}
public TreeNode recur(int[] preorder,int[] inorder,int m,int n,int p,int q){
//m n 是 先序的边界
// p q 是 中序的边界
//用先序找根,先序的第一个节点,就是根
//精髓就在如何定义这个边界
if (p > q) return null;
TreeNode root = new TreeNode(preorder[m]);
int index = map.get(preorder[m]);
int num_left = index - p;
root.left = recur(preorder,inorder,m+1,m+num_left,p,index-1);//定义给这棵树的左子树
root.right = recur(preorder,inorder,m+num_left+1,n,index+1,q);//定义给这棵树的右子树
return root;
}
这道题就有很多小技巧
- 使用了一个hashmap来记录中序遍历的节点与对应的索引。方便划分左子树与右子树。
- 它的终止条件是 p > q。当p=q的时候,说明这个是一个叶子节点,他没有子节点了,当p>q的时候就跳出循环。
- 记录下左子树的个数,帮助划分
106 从中序与后序遍历序列构造二叉树
HashMap<Integer,Integer> map;
public TreeNode buildTree(int[] inorder, int[] postorder) {
map = new HashMap<Integer, Integer>();
int count = 0;
for (int i :inorder)map.put(i,count++);
return recur(inorder,postorder,0,inorder.length-1,0,postorder.length-1);
}
public TreeNode recur(int[] inorder,int[] postorder,int m,int n,int p,int q){
//用后续遍历确定根,p q是后续遍历的界
//用中序遍历划分左子树和右子树,m n 是中序遍历的界
if (m>n) return null;
TreeNode root = new TreeNode(postorder[q]);
int index = map.get(root.val);
int num_left = index - m;
root.left = recur(inorder,postorder,m,index-1,p,p+num_left-1);
root.right = recur(inorder,postorder,index+1,n,p+num_left,q-1) ;
return root;
}
思路是相同的,就拿来练手,关键还是左子树右子树的划分区域
654 最大二叉树
比前面两题还要简单 = - =
HashMap<Integer,Integer> map;
public TreeNode constructMaximumBinaryTree(int[] nums) {
map = new HashMap<Integer, Integer>();
int count = 0;
for(int i:nums) map.put(i,count++);
return recur(nums,0,nums.length-1);
}
public TreeNode recur(int[] nums,int p,int q){
if (p > q) return null;
int max = findmax(nums,p,q);
TreeNode root = new TreeNode(max);
int index = map.get(max);
System.out.println(max);
root.left = recur(nums,p,index-1);
root.right = recur(nums,index+1,q);
return root;
}
public int findmax(int[] nums,int p,int q){
int max = -1;
for (int i = p;i<=q;i++){
if (max < nums[i])
max = nums[i];
}
return max;
}
617 合并二叉树
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
if (root1 == null && root2 == null) return null;
if (root1 == null && root2 != null) return root2;
if (root1 != null && root2 == null) return root1;
TreeNode root = new TreeNode(root1.val+root2.val);
root.left = mergeTrees(root1.left,root2.left);
root.right = mergeTrees(root1.right,root2.right);
return root;
}
体会这个思想,这也是我自己做出来的,很简单一个递归。我的思路很简单。在当前节点我需要做什么事情。
- 判断root1 root2同时为空,直接返回空,root1 root2有一个为空,则另一直接返回。root1 root2都不为空,就返回两者的和,并且继续发展左子树与右子树
700 二叉搜索树中的搜索
public TreeNode searchBST(TreeNode root, int val) {
if (root == null) return null;
if (root.val == val) return root;
if (root.val < val) return searchBST(root.right,val);
if (root.val > val) return searchBST(root.left,val);
return null;
}
很简单,就是二叉搜索树的简单遍历
验证二叉搜索树
对于这题,一开始我使用递归的思想,保证root root.left root.right的一致性,却不能保证整体,只考虑了局部。
第二个思路
public boolean isValidBST(TreeNode root) {
if (root == null) return true;
if (root.left == null && root.right!=null) return recur_1(root.left,root.val) && recur_2(root.right,root.val) && isValidBST(root.right);
if (root.left != null && root.right ==null) return recur_1(root.left,root.val) && recur_2(root.right,root.val) && isValidBST(root.left);
return recur_1(root.left,root.val) && recur_2(root.right,root.val) && isValidBST(root.left) && isValidBST(root.right);
}
public boolean recur_1(TreeNode root,int val){
if (root == null) return true;
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
while (!queue.isEmpty()){
TreeNode poll = queue.poll();
if (poll.val >= val ) return false;
if (poll.left != null) queue.add(root.left);
if (poll.right != null) queue.add(root.right);
}
return true;
}
public boolean recur_2(TreeNode root,int val){
if (root == null) return true;
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
while (!queue.isEmpty()){
TreeNode poll = queue.poll();
if (poll.val <= val ) return false;
if (poll.left != null) queue.add(root.left);
if (poll.right != null) queue.add(root.right);
}
return true;
}
暴力求解。对于每一个root,保证左子树全部节点小于root节点,对于右子树保证所有节点大于root节点。这样会造成很多次无效计算。
这道题关键在于二叉树的中序遍历是有序的这一点。
LinkedList<Integer> list = new LinkedList<Integer>();
public boolean isValidBST(TreeNode root) {
if (root == null) return true;
int pre = -1;
for (int i = 0;i<list.size();i++){
if (i == 0) {
pre = list.get(i);
continue;
}
if (list.get(i) <= pre) return false;
pre = list.get(i);
}
return true;
}
public void recur(TreeNode root){
if (root == null) return;
recur(root.left);
list.add(root.val);
recur(root.right);
}
我这里是先记录了搜索二叉树,中序遍历的路径。再对路径进行比较
501 二叉搜索树中的众数
LinkedList<Integer> list = new LinkedList<Integer>();
public int[] findMode(TreeNode root) {
LinkedList<Integer> list_2 = new LinkedList<Integer>();
HashMap<Integer,Integer> map = new HashMap<Integer, Integer>();
int pre = -1;
int category = 1;
int max_category = 1;
for (int i = 0;i < list_2.size();i++){
if (i == 0)
pre = list_2.get(i);
if (list_2.get(i) == pre){
category++;
}else {
map.put(pre,category);
System.out.println(pre);
System.out.println(category);
if (max_category < category)
max_category = category;
pre = list.get(i);
category = 1;
}
}
for (Map.Entry<Integer,Integer>entry:map.entrySet()){
if (entry.getValue() == max_category)
list.add(entry.getKey());
}
int[] res = new int[list.size()];
for (int i =0;i<list.size();i++){
res[i] = list.get(i);
}
return res;
}
public void recur(TreeNode root){
if (root == null) return;
recur(root.left);
list.add(root.val);
recur(root.right);
}
思路,这题我没通过,不想改了,脑壳能。
思路1就是首先找到顺序,第二统计出现频率,第三找到频率最高的几个数组成数组输出。
236 二叉树的最近公共祖先
我的思路很简单,虽然没有通过测试,主要是因为我的算法效率太低了,能解决问题是能的,这道题的第30个样例,树太大了,直接让我gg
我的思路很简单,第一步找到所有的公共祖先,放进一个列表,求这个这些祖先在哪一层。找到层数最大的,返回。这就是我的思路
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
Queue<TreeNode> queue = new LinkedList<TreeNode>();
LinkedList<TreeNode> list = new LinkedList<TreeNode>();
queue.add(root);
while (!queue.isEmpty()){
TreeNode poll = queue.poll();
if (isArrive(poll,p) && isArrive(poll,q)) list.add(poll);
if (poll.left != null) queue.add(poll.left);
if (poll.right != null) queue.add(poll.right);
}
int layer = -1;
for (TreeNode treeNode:list){
System.out.println(treeNode.val);
int i = num_layer(root, treeNode);
if (i>layer) layer = i;
}
for (TreeNode treeNode:list){
if (layer == num_layer(root,treeNode))
return treeNode;
}
return null;
}
public boolean isArrive(TreeNode root,TreeNode p){
if (root == null) return false;
boolean tag = false;
if (root.val == p.val)
tag = true;
return tag || isArrive(root.left,p) || isArrive(root.right,p);
}
但是这样子做明显不符合要求。