- 问题描述
求二叉树两个节点的最近公共父节点。
- 解决方案1
首先找到根节点到两个节点的路径,然后将其中一个路径加入到哈希表中,然后遍历另一个路径,在哈希表中有相同的则返回即可,代码如下:
public static TreeNode lowestCommenAncestor(TreeNode root,TreeNode p,TreeNode q){
List<TreeNode> listP = getPath(root,p);
List<TreeNode> listQ = getPath(root,q);
HashSet<TreeNode> set = new HashSet<>();
for(int i = 0;i < listP.size();i ++)
set.add(listP.get(i));
for (int i = 0; i < listQ.size(); i++) {
if(set.contains(listQ.get(i)))
return listQ.get(i);
}
return null;
}
//获取从root节点到p节点的路径
public static List<TreeNode> getPath(TreeNode root, TreeNode p){
List<TreeNode> list = new LinkedList<>();
isContainsNode(root, p,list);
return list;
}
//检测某个节点的孩子是否包含某个节点,并找到路径加入到List中
public static boolean isContainsNode(TreeNode root, TreeNode p,List<TreeNode> list){
if(root == null)
return false;
if(root == p){
list.add(p);
return true;
}
else if(isContainsNode(root.left,p,list) || isContainsNode(root.right,p,list)){
list.add(root);
return true;
}
return false;
}
- 解决方案2
直接用递归来解决,比较难想明白,但是代码非常简洁:
public static TreeNode lowestCommenAncestor2(TreeNode root,TreeNode p,TreeNode q){
if(root == null || root == p || root == q)
return root;
TreeNode left = lowestCommenAncestor2(root.left,p,q);
TreeNode right = lowestCommenAncestor2(root.right,p,q);
if(left != null && right != null)
return root;
return left != null ? left : right;
}
- 测试
测试代码如下:
public static void main(String[] args) {
//测试如下二叉树
// 1
// / \
// 2 3
// / \ / \
// 4 5 6 7
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);
root.right = new TreeNode(3);
root.right.left = new TreeNode(6);
root.right.right = new TreeNode(7);
//4和5的父节点
System.out.println(lowestCommenAncestor(root,root.left.left,root.left.right).val);
System.out.println(lowestCommenAncestor2(root,root.left.left,root.left.right).val);
//2和7的父节点
System.out.println(lowestCommenAncestor(root,root.left,root.right.right).val);
System.out.println(lowestCommenAncestor2(root,root.left,root.right.right).val);
}