您的位置:首页 > 职场人生

【剑指offer】 面试题50: 树中两个结点的最低公共祖先

2015-06-09 20:34 726 查看
题目描述:

给定一棵树,同时给出树中的两个结点,求它们的最低公共祖先。

1 2 4 6 0 0 7 0 0 5 8 0 0 9 0 0 3 0 0
6 8

存在, 2

1 2 4 6 0 0 7 0 0 5 8 0 0 9 0 0 3 0 0
6 12


不存在

方法一:

后序遍历

 

基本思想:

1、两个节点不在一条线上(即两个节点不存在一个节点是另一个节点的祖先的情况),则它们必定分别在所求节点A的左子树和右子树上,

后序遍历到第一个满足这个条件的节点就是所要求的节点A。

2、当这两个节点在一条线上,所求节点A则是这两个节点中深度最低的节点的父节点。

package com.offer.chapter_7;

import java.util.Scanner;

class BinaryTreeNode {
public int elem;
public BinaryTreeNode left;
public BinaryTreeNode right;
}

/**
* @author hadoop
*
* 求二叉树中任意两个节点的最近公共祖先也称为LCA问题(Lowest Common Ancestor)
*
*/
public class Interviews_50 {
public static int curIndex = 0;

public static BinaryTreeNode result = null;

/**
*
* 构建二叉树
*
*/
public static void createBinaryTree(BinaryTreeNode curRoot, int[] data) {
int leftElem = data[curIndex ++];

if(leftElem == 0) {
curRoot.left = null;
} else {
BinaryTreeNode leftChild = new BinaryTreeNode();
leftChild.elem = leftElem;
leftChild.left = leftChild.right = null;

curRoot.left = leftChild;

createBinaryTree(curRoot.left, data);
}

int rightElem = data[curIndex ++];

if(rightElem == 0) {
curRoot.right = null;
} else {
BinaryTreeNode rightChild = new BinaryTreeNode();
rightChild.elem = rightElem;
rightChild.left = rightChild.right = null;

curRoot.right = rightChild;

createBinaryTree(curRoot.right, data);
}
}

/**
*
* 基本思想:如果这两个节点不在一条线上(即这两个节点不存在一个节点是另一个节点的祖先的情况),则它们必定分别在所求节点A的左子树和右子树上,
* 后序遍历到第一个满足这个条件的节点就是所要求的节点A。否则,当这两个节点在一条线上,所求节点A则是这两个节点中深度最低的节点的父节点。
*
* result 始终记录当前是否已经找到目标共同祖先结点
*
*/
public static int findLowestCommonAncestor(BinaryTreeNode curRoot, int a, int b, BinaryTreeNode parent) {
int left = 0;
int right = 0;
// 判断左子树是否含有要判断的两节点之一
if(result == null && curRoot.left != null) {
left = findLowestCommonAncestor(curRoot.left, a, b, curRoot);
}
// 判断右子树是否含有要判断的两节点之一
if(result == null && curRoot.right != null) {
right = findLowestCommonAncestor(curRoot.right, a, b , curRoot);
}

// 判断当前结点是否是所查找结点之一
int mid = 0;
if(curRoot.elem == a || curRoot.elem ==b) {
mid = 1;
}
// 当前已经找到两个结点
if(result == null && (left + right + mid) == 2) {
// 如果两个结点在一条路径上,则当前结点的父节点为共同祖先结点
if(mid == 1) {
result = parent;
} else {
// 如果分别在当前结点的左右子树上,则当前结点为共同祖先结点
result = curRoot;
}
}
// 返回当前子树中包含查找结点的个数
return (left + right + mid) > 0 ? 1 : 0;
}

/**
* 二叉树中任意两个节点的最近公共祖先
*/
public static void LowestCommonAncestor(BinaryTreeNode root, int a, int b) {
result = null;

if(root == null) {
return;
}

findLowestCommonAncestor(root, a, b, null);
}

public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int num = scanner.nextInt();

while(num -- > 0) {
BinaryTreeNode root = null;
scanner.nextLine();
String string = scanner.nextLine();
String[] strs = string.split(" ");
int[] data = new int[strs.length];

int a = scanner.nextInt();
int b = scanner.nextInt();

for(int i=0; i<strs.length; i++) {
data[i] = Integer.parseInt(strs[i]);
}

if(data.length < 2) {
System.out.println("My God");
} else {
root = new BinaryTreeNode();
root.elem = data[0];
curIndex = 1;
createBinaryTree(root, data);

LowestCommonAncestor(root, a, b);

if(result == null) {
System.out.println("My God");
} else {
System.out.println(result.elem);
}
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息