Leetcode 236 二叉树的最近公共祖先
236. 二叉树的最近公共祖先
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
示例 1:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出: 3
解释: 节点 5
和节点 1
的最近公共祖先是节点 3
。
示例 2:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出: 5
解释: 节点 5
和节点 4
的最近公共祖先是节点 5
。因为根据定义最近公共祖先节点可以为节点本身。
示例 3:
输入: root = [1,2], p = 1, q = 2
输出: 1
提示:
- 树中节点数目在范围
[2, 10^5]
内。 -10^9 <= Node.val <= 10^9
- 所有
Node.val
互不相同 。 p != q
p
和q
均存在于给定的二叉树中。
Related Topics
- 树
- 深度优先搜索
- 二叉树
题目链接: link
解答
本题的难度是 Medium.
写了一个很抽象的代码, 感觉最近写的代码都很抽象, 这里我考虑记录每一个节点当前的深度和父节点的值, 然后再遍历一遍, 找到两个节点的深度, 然后让深度深的节点向上走, 直到两个节点的深度相同, 然后再一起向上走, 直到两个节点相遇, 这个节点就是最近公共祖先. 代码如下:
class Solution {
private HashMap<Integer, Integer> depthMap = new HashMap<>();
private HashMap<Integer, Integer> parentMap = new HashMap<>();
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
// 一个HashMap 记录深度, 一个HashMap 记录父节点是什么
BTS(root,0, null);
int pVal = p.val;
int qVal = q.val;
int pDepth = depthMap.get(pVal);
int qDepth = depthMap.get(qVal);
if (pDepth < qDepth){
for (int i = 0; i < qDepth-pDepth; i++) {
qVal = parentMap.get(qVal);
}
} else {
for (int i = 0; i < pDepth-qDepth; i++) {
pVal = parentMap.get(pVal);
}
}
while (pVal != qVal){
pVal = parentMap.get(pVal);
qVal = parentMap.get(qVal);
}
// 如果这边不许创建新节点, 我甚至打算搞一个 Map 存储节点的引用
return new TreeNode(pVal);
}
private void BTS(TreeNode node, int depth, TreeNode parent){
if(node == null){
return;
}
if (parent == null){
parentMap.put(node.val, null);
} else {
parentMap.put(node.val, parent.val);
}
depthMap.put(node.val, depth);
if (node.left != null) {
BTS(node.left, depth+1, node);
}
if (node.right != null) {
BTS(node.right, depth+1, node);
}
}
}
因为这个代码实在太抽象了, 因此时间开销 9ms, 只击败了 15.14% 的提交. 现在写一个正经一点的版本.
如果 p 和 q 分别在当前节点的左右子树, 那么当前节点就是最近公共祖先, 如果 p 和 q 都在左子树, 那么就在左子树找, 如果 p 和 q 都在右子树, 那么就在右子树找. 代码如下:
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null || root == p || root == q) {
return root;
}
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if (left == null) {
return right;
}
if (right == null) {
return left;
}
return root;
}
}
这个代码时间开销为 7ms, 击败了 69% 的提交, 这边其实也很抽象, 因为这个代码不是我写的, 我准备写的, 把思路写下来 copilot直接帮我生成了….
但是也懒得再改.