LeetCode Java刷题笔记—236. 二叉树的最近公共祖先
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
中等难度,和是同一道题,是的升级版。
这种题就是经典的LCA问题,采用递归分治+自底向上后序遍历即可用较少的代码写出来。
public TreeNode lowestCommonAncestor( TreeNode root, TreeNode p, TreeNode q ){ //递归返回的条件,要么root为null,这表示可能是递归到了最底层 //要么root等于p或者q,这表示已经找到了等于p或者q的节点,没必要继续向下递归 if( root == null || root == p || root == q ){ return root; } /*分 拆解*/ TreeNode left = lowestCommonAncestor( root.left, p, q ); TreeNode right = lowestCommonAncestor( root.right, p, q ); /*治 合并*/ //如果左右子节点都不null,那么表示p和q都是找到了,那么返回root父节点 //如果有一个子节点为null,那么返回另一个节点,这表示最近公共祖先就是另一个节点 //最终将会导致这个函数要么返回null,表示没有最近公共祖先 //要么返回p或者q节点,表示两个节点的最近公共祖先是其中一个节点 //要么返回root,表示两个节点的最近公共祖先是该节点 return left == null ? right : right == null ? left : root; }
另一种方法思想更加简单,我们可以用哈希表存储所有节点的父节点,然后我们就可以利用节点的父节点信息从 p 结点开始不断往上跳,并记录已经访问过的节点,再从 q 节点开始不断往上跳,如果碰到已经访问过的节点,那么这个节点就是我们要找的最近公共祖先。
//存储子节点和父节点的关系映射 Map<Integer, TreeNode> parent = new HashMap<Integer, TreeNode>(); Set<Integer> visited = new HashSet<Integer>(); public TreeNode lowestCommonAncestor( TreeNode root, TreeNode p, TreeNode q ){ //将整棵树的父子节点关系存储起来 dfs( root ); //循环存储从p节点开始到其父节点的路径 while( p != null ){ visited.add( p.val ); p = parent.get( p.val ); } //同样从q节点开始循环查找其父节点是否在这条路径中 while( q != null ){ //如果路径中包含q,那么返回q,即q就是最近公共祖先 if( visited.contains( q.val ) ){ return q; } q = parent.get( q.val ); } return null; } /** * 将整棵树的父子节点关系存储起来 * * @param root */ public void dfs( TreeNode root ){ if( root.left != null ){ parent.put( root.left.val, root ); dfs( root.left ); } if( root.right != null ){ parent.put( root.right.val, root ); dfs( root.right ); } }
下一篇:
邻接表的深度优先遍历