在二叉树中找到两个节点的最近公共祖先
来源:互联网 发布:java项目怎么绑定域名 编辑:程序博客网 时间:2024/06/04 23:18
程序员代码面试指南(左程云)读书笔记
第三章
在二叉树中找到两个节点的最近公共祖先
题目:
给定一棵二叉树的头节点head,以及这棵二叉树的两个节点o1和o2,请返回o1和o2的最近公共祖先节点。
解答:
后序遍历二叉树,假设遍历到的当前结点为cur,因为是后序遍历,所以先处理cur的两颗子树,假设处理cur左子树时返回left,处理右子树时返回right.
1,如果发现cur等于null,或者o1,o2。则返回cur.
2,如果left和right都为空,说明cur整棵子树都没有发现过o1 和o2,返回null.
3.如果left和right都不为空,说明左子树上发现过o1 和 o2,右子树上也发现过o1 和o2,说明o1 向上与o2向上的过程中,首次在cur相遇,返回cur.
4,如果left和right是有一个为空,另一个不为空,假设不为空的那个记为node,此时又两种肯,要么node是o1或o2中的一个,要么node已经是o1和o2的最近公共祖先节点,此时直接返回node即可。
代码如下:
public TreeNode lowestAcnestor(TreeNode head,TreeNode o1,TreeNode o2){
if(head==null){return head;}
//在左子树中查找目标节点
TreeNode left=lowestAcnestor(head.left,o1,o2);
//在右子树中查找目标节点
TreeNode right=lowestAcnestor(head.right,o1,o2);
if(left!=null && right!=null){return head;}
return left!=null?left:right;
}
public class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode (int val) {this. val = val; }
}
进阶问题:
如果查询两个节点的最近公共祖先的操作十分频繁,想办法让单条查询的查询时间减少。
这个问题其实是先花较大的力气建立一种记录,以后执行每次查询时就可以完全根据记录进行查询。
结构一:建立二叉树中每个节点对应的父节点信息,是一张哈希表。
如果对题目中的二叉树建立这种哈希表,如下图所示:
代码:
import java.util.HashMap;
import java.util.HashSet;
public class ParentNode2 {
private HashMap<TreeNode, TreeNode> map;
public ParentNode2(TreeNode head) {
map=new HashMap<TreeNode ,TreeNode>();
if(head!=null){
map.put(head, null);
setMap(head);
}
}
public void setMap(TreeNode head) {
if(head==null){return ;}
if(head.left!=null){map.put(head.left, head);}
if(head.right!=null){map.put(head.right, head);}
setMap(head.left);
setMap(head.right);
}
public TreeNode query(TreeNode o1,TreeNode o2){
HashSet<TreeNode> path=new HashSet<TreeNode>();
while(map.containsKey(o1)){
path.add(o1);
o1=map.get(o1);
}
while(!path.contains(o2)){
o2=map.get(o2);
}
return o2;}
}
结构二:
直接建立任意两个节点之间的最近公共祖先记录,便于以后查询时直接查。
过程如下:
1,对二叉树的每颗子树(一共N课)都进行步骤2.
2,假设子树的头节点为h,h所有的后代节点和h节点的最近公共祖先节点都是h,记录下来,h左子树的每个节点和h右子树的每个节点的最近公共祖先都是h,记录下来。
为了保证记录不重复,设计一种好的实现方法是重点。
package com.chen.zuocengyun;
import java.util.HashMap;
//在二叉树中找到两个节点的最近公共祖先节点
public class ParentNode3 {
private HashMap<TreeNode, HashMap<TreeNode,TreeNode>> map;
public ParentNode3(TreeNode head){
map=new HashMap<TreeNode,HashMap<TreeNode,TreeNode>>();
initMap(head);
setMap(head);
}
private void setMap(TreeNode head) {
if(head==null){return;}
headRecord(head.left,head);
headRecord(head.right,head);
subRecord(head);
setMap(head.left);
setMap(head.right);
}
private void headRecord(TreeNode n, TreeNode h) {
if(n==null){return;}
map.get(n).put(h, h);
headRecord(n.left, h);
headRecord(n.right, h);
}
private void subRecord(TreeNode head) {
if(head==null){
return;
}
preLeft(head.left,head.right,head);
subRecord(head.left);
subRecord(head.right);
}
private void preLeft(TreeNode l, TreeNode r, TreeNode h) {
if(l==null){return;}
preRight(l,r,h);
preLeft(l.left, r, h);
preLeft(l.right,r,h);
}
private void preRight(TreeNode l, TreeNode r, TreeNode h) {
if(r==null){return;}
map.get(l).put(r, h);
preRight(l, r.left, h);
preRight(l, r.right, h);
}
private void initMap(TreeNode head) {
if(head==null){return;}
map.put(head, new HashMap<TreeNode,TreeNode>());
initMap(head.left);
initMap(head.right);
}
public TreeNode query(TreeNode o1,TreeNode o2){
if(o1==o2){return o1;}
if(map.containsKey(o1)){return map.get(o1).get(o2);}
if(map.containsKey(o2)){return map.get(o2).get(o1);}
return null;
}
}
0 0
- 二叉树中找到两个节点的最近公共祖先
- 二叉树系列---在二叉树中找到两个节点的最近公共祖先
- 在二叉树中找到两个节点的最近公共祖先
- 在二叉树中找到两个节点的最近公共祖先
- 二叉树中两个节点的最近公共祖先节点
- 二叉树中两个节点的最近公共祖先节点
- 二叉树中两个节点的最近公共祖先节点
- 二叉树中两个节点的最近公共祖先节点
- 求二叉树中两个节点的最近公共祖先
- 求二叉树中两个节点的最近公共祖先
- 求二叉树中两个节点的最近公共祖先
- 求二叉树中两个节点的最近公共祖先
- 求二叉树中两个节点的最近公共祖先
- 二叉树问题---在二叉树中找到两个节点的最近公共节点
- 树——在二叉树中找到两个节点的最低公共祖先LCA
- 求两个节点的最近公共祖先多种解法&&判断一个节点是否在二叉树中
- 【转载】二叉树中两个节点的最近公共祖先节点
- 求二叉树中两个节点的最近公共祖先节点
- 建议13: 为类型输出格式化字符串(1)
- 【Java基础】多线程——基础
- 用nodePPT制作ppt
- 常用开源服务器库和中间件
- swift学习笔记 --- Collection Types
- 在二叉树中找到两个节点的最近公共祖先
- DWZ框架的分页组件点击不反应的问题
- oracle pl/sql split函数
- 矩阵乘法
- Batman+joker乱谈
- 基于手机号的黑白名单实现方案
- mysql的连接和实现功能
- 【Oracle】 sql 中的字符(串)替换与转换
- 根据app主包名判断某个apk是否存在