给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]
示例 1:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
输出: 6
解释: 节点 2 和节点 8 的最近公共祖先是 6。
示例 2:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
输出: 2
解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。
说明:
所有节点的值都是唯一的。
p、q 为不同节点且均存在于给定的二叉搜索树中。
解题思路:
法1:两次寻找。寻找节点p并沿途将经过的节点存入队列,寻找节点q并沿途将经过的节点存入另一个队列。在队列都不为空的情况下,两个队列同时出队直到出队元素不同,则上一次出队的元素即为公共祖先。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
boolean flagp = false;
boolean flagq = false;
Queue<TreeNode> queuep = new LinkedList<TreeNode>();
Queue<TreeNode> queueq = new LinkedList<TreeNode>();
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
TreeNode ret = new TreeNode();;
searchp(root, p);
searchq(root, q);
while(!queueq.isEmpty() && !queuep.isEmpty() && queuep.peek().val == queueq.peek().val){
ret = queuep.poll();
queueq.poll();
}
return ret;
}
public void searchp(TreeNode root, TreeNode p){
if(flagp == true) return;
if(flagp == false && p.val > root.val){
queuep.offer(root);
searchp(root.right, p);
}
else if(flagp == false && p.val < root.val){
queuep.offer(root);
searchp(root.left, p);
}
else if(flagp == false && p.val == root.val){
queuep.offer(root);
return;
}
}
public void searchq(TreeNode root, TreeNode q){
if(flagq == true) return;
if(flagq == false && q.val > root.val){
queueq.offer(root);
searchq(root.right ,q);
}
else if(flagq == false && q.val < root.val){
queueq.offer(root);
searchq(root.left ,q);
}
else if(flagq == false && q.val == root.val){
queueq.offer(root);
return;
}
}
两个查找方法目的是存入两个队列,也可以新建两个队列,将其作为形参传入查找方法。
时间复杂度是O(n),空间复杂度是O(n)。n是二叉树节点数。
法2:一次查找法。利用二叉树存储的特点,p和q的共同祖先的val必然满足要求:
p.val >= root.val && q.val <= root.val || p.val <= root.val && q.val >= root.val
而另外两种情况分别是p、q在当前节点的左侧或右侧,需要继续向下寻找。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
while(true){
if(p.val >= root.val && q.val <= root.val || p.val <= root.val && q.val >= root.val)
return root;
if(p.val > root.val && q.val > root.val)
root = root.right;
if(p.val < root.val && q.val < root.val)
root = root.left;
}
}
}
时间复杂度:O(n),空间复杂度:O(1)。n是二叉树节点数。