公共祖先题意:
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
力扣:236. 二叉树的最近公共祖先 - 力扣(LeetCode)
思路:
p或q在根上,根就是公共祖先;
图示:
一个在根左边,一个在根右边;
图示:
两个都在根左边 或者 两个都在根右边;
图示:
要么就是一颗空树;
代码实现:
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
}
递归实现:
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
//1.如果根节点是空,直接是空;
if(root == null) {
return null;
}
//2.如果p或者q等于root返回root
if(root.val == q.val || root.val == p.val) {
return root;
}
//3.在左树里面去找q或者p
TreeNode leftTree = lowestCommonAncestor(root.left,p,q);
TreeNode rightTree = lowestCommonAncestor(root.right,p,q);
if(leftTree != null && rightTree != null) {
return root;
//两个都在左,返回在左边找到的第一个节点
} else if (leftTree != null) {
return leftTree;
//两个都在右,返回在右边找到的第一个节点
} else if(rightTree != null) {
return rightTree;
}
return null;
}
使用栈来实现:
思路:
把到p节点路线节点存到栈当中,q也一样,谁大,让谁多走到栈相同大小,然后再同时出栈,并且判断;
图例:
总结:
1.把p和q的路线节点存进栈内
2.判断即可
代码示例:
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
//1.把数据全部放进栈中
//2.再进行判断
Stack<TreeNode> stack1 = new Stack<>();
//把P传入栈中
getpath(root, p, stack1);
//把q传入栈中
Stack<TreeNode> stack2 = new Stack<>();
getpath(root, q, stack2);
//此刻的stack1和2已经存放进去p和q路径的数据了
int x1 = stack1.size();
int x2 = stack2.size();
//让栈中元素多的先出,出到栈内大小一致为止
if (x1 > x2) {
int a = x1 - x2;
while (a != 0) {
stack1.pop();
a--;
}
} else {
int a = x2 - x1;
while (a != 0) {
stack2.pop();
a--;
}
}
//出栈内的元素也就是栈1和栈2不为空,一直出到元素一致,否则则没有
while (!stack1.isEmpty() && !stack2.isEmpty()) {
if (stack1.peek() != stack2.peek()) {
stack1.pop();
stack2.pop();
} else {
return stack1.pop();
}
}
//如果走到这说明栈为空,且没有q或者p,直接返回null
return null;
}
//创建一个函数专门找p或q的数据并且存放到栈当中去
public boolean getpath(TreeNode root,TreeNode node,Stack<TreeNode> stack){
//进来是找P或者Q的数据,并存放到栈当中去,那也就是说,node和root不能为空
if(root == null || node == null) return false;
//如果不为空呢?
stack.push(root);
if(root == node) return true;
boolean leftTree = getpath(root.left,node,stack);
if(leftTree) return true;
boolean rightTree = getpath(root.right,node,stack);
if(rightTree) return true;
stack.pop();
return false;
}