问题:求二叉树的两个节点最近公共祖先
我的解决思路:如果两个节点都在二叉树中,求出分别到两个节点的路径,然后两个路径集合求交,得到结果集的最后一个元素即为最近公共祖先
所以问题分解到:
1.节点是否在二叉树中存在
public boolean binSearch(int n,TreeNode root){
if(root==null){
//定义出口1
return false;
}
if(root.val==n){
//定义出口2
return true;
}
boolean found = binSearch(n, root.left);//查找左子树
if(!found){
//如果左子树没找到,查找右子树
binSearch(n, root.right);
}
return found;
}
这里返回时有三种可能,1.查找到(出口2)2.叶子节点没查找到(出口2)3.左子树上没有要返回右子树(设置found来返回)
2.求根到某一节点路径集合
public LinkedList<Integer> binPath(int n, TreeNode root) {
LinkedList<Integer> ret = new LinkedList<Integer>();
retAdd(n,root,ret);
return ret;
}
public void retAdd(int n,TreeNode root,LinkedList<Integer> ret){
if (!binsearch.binSearch(n, root)) {
return;
} else {
ret.add(root.val);
}
retAdd(n, root.left,ret);
retAdd(n, root.right,ret);
}
这里印象深刻的是,要用一个list存储路径上的个点,在binPath直接new然后递归binPath得到答案是根节点,最后想了想用static list,可每次调用上次存放的值还在list中,这也不对,所以再写函数调用,把new list与递归过程分开,对,就是把这两个分开。
3.用两个集合的交集
public List<Integer> setIntersection(List list1, List list2) {
List ret = new LinkedList<Integer>();
int i = 0;
while (i < list1.size()) {
int j = 0;
while (j < list2.size()) {
if (list2.get(j) == list1.get(i)) {
ret.add(list1.get(i));
}
j++;
}
i++;
}
return ret;
}
所以问题就变成了:
1.判断两个节点是否都在二叉树中
2.分别求出两个节点的路径集合
3.求交,输出最后一个值
public int lowestCommonAncester(int n1, int n2, TreeNode root) {
int ret;
if (!new BinSearch().binSearch(n1,root) || !new BinSearch().binSearch(n2,root)) {
return -1;
}else{
LinkedList<Integer> list1 = new BinPath().binPath(n1, root);
LinkedList<Integer> list2 = new BinPath().binPath(n2, root);
List list = new SetIntersection().setIntersection(list1, list2);
ret = (Integer) list.get(list.size()-1);
}
return ret;
}
分析:算法复杂度为O(
n²),可以改进