题目链接:LeeCode236二叉树的最近公共祖先
题目描述:
起初是自己想了一个思路,将树的前序遍历存到list里,每次查p,q在左子树区间还是右子树区间,如果都在左或者都在右,那就将这个区间放进去接着找,如果一左一右,那就返回当前节点,这是我自己的代码,时间300+ms,太low了
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public static TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
List<TreeNode> curlist=prelist(root,new ArrayList<>());
return find(root, p, q,curlist,curlist.subList(1,curlist.size()),null);
}
public static TreeNode find(TreeNode root,TreeNode p,TreeNode q,List<TreeNode> curlist,List<TreeNode> list1,List<TreeNode> list2){
if(curlist.get(0).right!=null){
list1=curlist.subList(1,curlist.indexOf(curlist.get(0).right));
list2=curlist.subList(curlist.indexOf(curlist.get(0).right),curlist.size());
}
boolean pinleft=list1.contains(p),qinleft=list1.contains(q);
if((root==p||root==q)){
return root;
}
if(pinleft!=qinleft)return root;
else {
if(pinleft==true)return find(root.left,p,q,list1,list1.subList(1,list1.size()),null);
else return find(root.right, p, q,list2,list2.subList(1,list2.size()),null);
}
}
public static List<TreeNode> prelist(TreeNode root,List<TreeNode> list){
if(root==null) return list;
list.add(root);
list=prelist(root.left,list);
list=prelist(root.right,list);
return list;
}
}
然后去题解里面翻翻想优化我这个,发现没有差不多思路的,但是看见了大神的题解,五体投地。
大概思路就是用后续遍历的思想,先将左右有没有p,q的情况返回上来,然后慢慢向上。
有几种情况:
1.当左右子树向父亲返回的是null,就证明当前节点的子节点或子节点的子节点都没有p,q
2.当左右子树返回的都不是null代表这个点就是想找的祖先节点
3.左右子树有一个是null的时候返回另一个的值(图出自leetcode大神)
class Solution {
public static TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
//如果搜到底了返回null,如果找到p,q了返回p,q
if(root==null||root==p||root==q)return root;
//向左递归
TreeNode left=lowestCommonAncestor(root.left,p,q);
//向右递归
TreeNode right=lowestCommonAncestor(root.right,p,q);
//左空返回右
if(left==null) return right;
//右空返回左
if(right==null) return left;
//代码如果能走到这代表都不空,则返回当前节点
return root;
}
}