给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。
如输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8;输出: 6 。解释: 节点 2 和节点 8 的最近公共祖先是 6。
既然给定的是二叉搜索树,则意味着树的左节点的值小于根节点,根节点的值小于右子节点。要求最近公共祖先有两种方式:
1.对二叉搜索树做两次遍历,分别找到root和p以及root和q的公共节点。定义两个集合path_p,path_q用来保存根节点到p节点和到q节点的路径。再次对path_p、path_q进行遍历,找到两个元素的不相同节点,则该节点的上一个节点即为深度最大的公共节点,也就是公共祖先。实现方法为lowestCommonAncestor。
2.对二叉搜索树只做一次遍历,定义变量temp对二叉搜索树进行遍历,并将的值.val和p、q节点的值进行大小比较,如果temp的节点值小于p和q的值,则公共祖先肯定在temp的右节点,将temp.right赋值给temp,继续循环;如果大于p和q,则公共祖先在temp的左节点,将temp.left赋值给temp,继续循环;如果是其他情况,则返回temp。实现方法为lowestCommonAncestorNew方法。
package leecodeOff;
/*
* 68.二叉搜索树的最近公共祖先
*/
import java.util.ArrayList;
import java.util.List;
public class Demo68 {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
path_p = getPath(root,p);
path_q = getPath(root,q);
int length_p = path_p.size();
int length_q = path_q.size();
if(length_p == 0 || length_q == 0) {
return null;
}
for(int i=0;i<length_p;i++) {
TreeNode node1 = path_p.get(i);
TreeNode node2 = path_q.get(i);
if(node1 != node2) {
return path_p.get(i-1);
}
}
return path_p.get(0);
}
List<TreeNode> path_p = new ArrayList<TreeNode>();
List<TreeNode> path_q = new ArrayList<TreeNode>();
public List<TreeNode> getPath(TreeNode root,TreeNode target) {
List<TreeNode> path = new ArrayList<TreeNode>();
while(root!=null) {
TreeNode temp = root;
path.add(temp);
if(target.val < temp.val) {
root = temp.left;
}else if(target.val > temp.val) {
root = temp.right;
}else {
break;
}
}
path.add(root);
return path;
}
//这个方法非常好
public TreeNode lowestCommonAncestorNew(TreeNode root, TreeNode p, TreeNode q) {
TreeNode temp = root;
while(true) {
int val1 = temp.val;
int val2 = p.val;
int val3 = q.val;
if(val2 < val1 && val3< val1) {
temp = temp.left;
}else if(val2 > val1 && val3>val1) {
temp = temp.right;
}else {
break;
}
}
return temp;
}
public static void main(String args[]) {
Demo68 demo = new Demo68();
TreeNode node1 = new TreeNode(6);
TreeNode node21 = new TreeNode(2);
TreeNode node22 = new TreeNode(8);
TreeNode node31 = new TreeNode(0);
TreeNode node32 = new TreeNode(4);
TreeNode node33 = new TreeNode(7);
TreeNode node34 = new TreeNode(9);
TreeNode node51 = new TreeNode(3);
TreeNode node52 = new TreeNode(5);
node1.left = node21;
node1.right = node22;
node21.left = node31;
node21.right = node32;
node22.left = node33;
node22.right = node34;
node32.left = node51;
node32.right = node52;
TreeNode node = demo.lowestCommonAncestor(node1, node21, node22);
System.out.println(node.val);
}
}