携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情 >>
一、题目描述 LeetCode-236
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
最近公共祖先的定义为:对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。
示例:
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3 。
示例:
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出:5
解释:节点 5 和节点 4 的最近公共祖先是节点 5 。因为根据定义最近公共祖先节点可以为节点本身。
二、解题思路
对于本题,先进行讨论如何得到p,q的最近公共祖先节点,主要分为以下几种情况:
- 节点p,q分布在根节点root的两侧,既分别在root节点的左右子树中,则最近公共祖先为root,直接返回;
- root = p,且节点q在root的左子树或右子树中,则返回节点p;
- root = q,且节点p在root的左子树或右子树中,则返回节点q;
在编写代码时考虑二叉树递归遍历方法,当遍历遇到p或q节点时返回。在进行返回时也分为几种情况:
- if (left != null && right != null) return root;
- if (left == null) return right;
- if (right == null) return left;
- if (left == null && right == null) return null;
三、代码
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
class Solution{
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null || p == root || q == root) {
return root;
}
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if (left == null && right == null){
return null;
}
if (left == null) {
return right;
}
if (right == null) {
return left;
}
return root;
}
}
四、总结
本题巧妙的利用二叉树回溯的思想,对左右子树进行判断并层层返回,最后得到p,q的最近公共祖先,时间复杂度和空间复杂度均为O(N),其中N为二叉树的节点树。