题解
-
题意:给出一个二叉树根节点
root
,以及两个子节点p
,q
,求p,q
的最低公共父节点,如下图,给出节点3
,节点6,7
要返回5
-
分析:什么叫做最低公共祖先?
- 祖先:如果一个节点的左子树或者右子树包含所需要寻找的两个节点p,q,那么说明左或者右子树中包含了他们的祖先
- 最低祖先:那么什么是最低祖先呢,有两种情况,一种情况是
p
就是q
的祖先,那么最低祖先就是p
,如果不是,那么就是当p,q
分布在一个节点的左右子树的时候,就是这个节点就是最低祖先,因为无论递归左子树还是右子树都会失去一个。
-
方法1:双重DFS(差点超时,复杂度应该是O(N^2))
- 做法:从根节点开始,每个节点都进行DFS,直到找到满足最低祖先的节点
class Solution{ public boolean dfs(TreeNode root, TreeNode p, TreeNode q){ if(root == null) return false; if(root.val == p.val || root.val == q.val) return true; return dfs(root.left,p,q) || dfs(root.right,p,q); } public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if(root==null) return null; if(root.val == p.val || root.val == q.val) return root; if(!dfs(root.right,p,q)) return lowestCommonAncestor(root.left, p, q); else if(!dfs(root.left,p,q)) return lowestCommonAncestor(root.right, p, q); else return root; } }
- 这种做法思路很简单,但是效率很低,因为每个节点都被冗余遍历了。
-
方法2:官方题解,使用额外变量记录目标节点,每次都判断一下是否满足最低祖先的要求
- 在dfs的时候,当前节点如果满足条件,那么就让
ans
记录
class Solution { private TreeNode ans; private boolean dfs(TreeNode root, TreeNode p, TreeNode q) { if (root == null) return false; boolean l = dfs(root.left,p,q); boolean r = dfs(root.right,p,q); if((l && r) || root.val==p.val || root.val==q.val) this.ans = root; return l||r||(root.val == p.val||root.val == q.val); } public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { this.dfs(root, p, q); return this.ans; } }
- 在dfs的时候,当前节点如果满足条件,那么就让