您的位置:首页 > 其它

在线笔试-求二叉树中俩个节点的最低共同父节点

2017-03-23 20:01 267 查看
昨天做美团点评的在线笔试题中遇到一道求二叉树中俩节点的最低父节点的题,当时写的很乱做完之后在网上查了下发现这种题目有很多变种很有意思,特意记录下来备忘。

求二叉树俩个节点的共同父节点大概有三种题型:

1、二叉树为双向链表

2、二叉树为二叉查找树

3、二叉树为普通二叉树

下面一一分析:

1、二叉树为双向链表

先建立数据模型:

package Binary_tree;

public class Node2 {//二叉树节点

private int data;
private Node2 leftNode;
private Node2 rightNode;
private Node2 parent=null;

public Node2(int data, Node2 leftNode, Node2 rightNode){
this.data = data;
this.leftNode = leftNode;
this.rightNode = rightNode;
}

public String toString(){

return String.valueOf(data);
}
省略get set方法。。。

}


基本思想:先分别找到俩个节点离根节点的距离,长的节点向上走使其长度与短平齐,之后俩个节点同时向上走直到俩个节点指向同一节点,则该节点便为俩个节点的统一父节点。如下代码便依此思想:

package Binary_tree;
public class Bothwaytree {
public Node2 getLp(Node2 root,Node2 a,Node2 b){
if(root==null)		return null;
int length1 = getLength(a);
int length2 = getLength(b);
if(length1>=length2){					//a节点的路径更长,a节点向上移动多出来的距离
int len = length1-length2;
for(int i=0;i<len;i++)
a=a.getParent();
}else{
int len = length2-length1;			//b节点的路径更长,b节点向上移动多出来的距离
for(int i=0;i<len;i++)
b=b.getParent();
}
while(a!=null&&b!=null){
if(a==b){	return a;				//a b同时向上移动当俩个节点移动到同一节点时即为统一父节点
}else{
a=a.getParent();
b=b.getParent();
}
}
return root;
}

private int getLength(Node2 node){			//获取该节点离根节点的距离
int count=0;
while(node!=null){
count++;
node=node.getParent();
}
return count;
}

public static void main(String[] args){
Node2 J = new Node2(8, null, null);
Node2 H = new Node2(4, null, null);
Node2 G = new Node2(2, null, null);
Node2 F = new Node2(7, null, J);
Node2 E = new Node2(5, H, null);
Node2 D = new Node2(1, null, G);
Node2 C = new Node2(9, F, null);
Node2 B = new Node2(3, D, E);
Node2 A = new Node2(6, B, C);
B.setParent(A);
C.setParent(A);
D.setParent(B);
E.setParent(B);
F.setParent(C);
G.setParent(D);
H.setParent(E);
J.setParent(F);
Bothwaytree bothtree = new Bothwaytree();
System.out.println(bothtree.getLp(A, G, H));
}
}


2、二叉树为二叉查找树
基本思想:在二叉查找树中俩个子节点的父节点的权值必是介于俩节点权值之间,故从根节点一直往下找,找到权值介于俩节点权值之间且最靠近叶子端的节点便是所求:

数据模型如下:

package Binary_tree;

public class Node {//二叉树节点

private int data;
private Node leftNode;
private Node rightNode;

public Node(int data, Node leftNode, Node rightNode){
this.data = data;
this.leftNode = leftNode;
this.rightNode = rightNode;
}

public String toString(){
return String.valueOf(data);
}

省略get set方法。。。

}


Java实现:

package Binary_tree;

public class Bintree {
public Node getLp(Node root,Node a,Node b){
while(root!=null){
if(root.getData()>a.getData()&&root.getData()>b.getData()){
root=root.getLeftNode();
}else if(root.getData()<a.getData()&&root.getData()<b.getData()){
root=root.getRightNode();
}
else
return root;
}
return null;
}
public static void main(String[] args){
Node J = new Node(35, null, null);
Node H = new Node(13, null, null);
Node G = new Node(7, null, null);
Node F = new Node(30, null, J);
Node E = new Node(15, H, null);
Node D = new Node(5, null, G);
Node C = new Node(40, F, null);
Node B = new Node(10, D, E);
Node A = new Node(20, B, C);
Bintree bintree = new Bintree();
System.out.println(bintree.getLp(A, G, J));
}
}


3、当二叉树为普通二叉树

基本思想:此时找俩节点的父节点有俩种情况:第一种是一个节点为另一个节点的父节点,则从上往下遍历 遍历到了俩节点之一的节点就直接返回。第二种是俩个节点在父节点的俩边,则递归向下遍历 找到了所求子节点之一就向上返回,否则向下遍历左右节点,左节点空就返回右节点,右节点空就返回左节点,若左右子节点都不空且都不为目标子节点则返回该节点。

代码如下:

package Binary_tree;

public class normalTree {

public Node getLp(Node root,Node a,Node b){
if(root==null)	return null;
if(root==a||root==b){
return root;
}
Node left = getLp(root.getLeftNode(),a,b);
Node right = getLp(root.getRightNode(),a,b);
if(left==null){
return right;
}else if(right==null){
return left;
}else
return root;
}

public static void main(String[] args){
Node J = new Node(35, null, null);
Node H = new Node(13, null, null);
Node G = new Node(7, null, null);
Node F = new Node(30, null, J);
Node E = new Node(15, H, null);
Node D = new Node(5, null, G);
Node C = new Node(40, F, null);
Node B = new Node(10, D, E);
Node A = new Node(20, B, C);
normalTree normaltree = new normalTree();
System.out.println(normaltree.getLp(A, D, G));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: