您的位置:首页 > 编程语言 > Java开发

树中两个节点的最低公共祖先(Java实现)

2017-05-22 09:59 561 查看
本题为剑指offer面试题50

在牛客网没有找到类似的题目,所以笔者自己建了三棵树进行测试

如有问题欢迎指正。

题目:求树中两个结点的最低公共祖先

分析:其实这是一组题目,考官没有说清楚树的结构,那么做法就不尽相同。

比如,如果是二叉搜索树的话,我们只需从根结点判断,如果二结点与根的左右子树比较一大一小,那么跟结点就是二者最低公共祖先;如果二结点都比左子结点小,向左子树递归进行比较;如果二结点都比右子树结点大,向右子树递归进行比较;

如果不是二叉搜索树,但带有指向父节点的指针,那么此题转换成在两个有相交的链表上求第一个相交点。

如果不带指向父节点的指针,那么我们可以记录从根结点到这两个结点的路径即可求出。

以下代码是:普通树(多个子树),子树没有指向父节点的指针

Java代码如下:
package go.jacob.day520;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import javax.management.RuntimeErrorException;

public class Demo1 {
public static void main(String[] args) {
test01();
System.out.println("==========");
test02();
System.out.println("==========");
test03();
}

// 形状普通的树
//             1
//           /   \
//         2      3
//        /         \
//      4            5
//     / \        /  |  \
//    6   7      8   9  10
public static void test01() {
TreeNode n1 = new Tree
d202
Node(1);
TreeNode n2 = new TreeNode(2);
TreeNode n3 = new TreeNode(3);
TreeNode n4 = new TreeNode(4);
TreeNode n5 = new TreeNode(5);
TreeNode n6 = new TreeNode(6);
TreeNode n7 = new TreeNode(7);
TreeNode n8 = new TreeNode(8);
TreeNode n9 = new TreeNode(9);
TreeNode n10 = new TreeNode(10);

n1.children.add(n2);
n1.children.add(n3);

n2.children.add(n4);

n4.children.add(n6);
n4.children.add(n7);

n3.children.add(n5);

n5.children.add(n8);
n5.children.add(n9);
n5.children.add(n10);

System.out.println(getLastCommonParent(n1, n9, n10));
}

// 树退化成一个链表
//               1
//              /
//             2
//            /
//           3
//          /
//         4
//        /
//       5
private static void test02() {
TreeNode n1 = new TreeNode(1);
TreeNode n2 = new TreeNode(2);
TreeNode n3 = new TreeNode(3);
TreeNode n4 = new TreeNode(4);
TreeNode n5 = new TreeNode(5);

n1.children.add(n2);
n2.children.add(n3);
n3.children.add(n4);
n4.children.add(n5);

System.out.println(getLastCommonParent(n1, n4, n5));
}

// 树退化成一个链表,一个结点不在树中
//               1
//              /
//             2
//            /
//           3
//          /
//         4
//        /
//       5
private static void test03() {
TreeNode n1 = new TreeNode(1);
TreeNode n2 = new TreeNode(2);
TreeNode n3 = new TreeNode(3);
TreeNode n4 = new TreeNode(4);
TreeNode n5 = new TreeNode(5);
TreeNode n6 = new TreeNode(6);

n1.children.add(n2);
n2.children.add(n3);
n3.children.add(n4);
n4.children.add(n5);

System.out.println(getLastCommonParent(n1, n5, n6));
}

/*
* 获取两个节点的最低公共祖先
*/
public static TreeNode getLastCommonParent(TreeNode root, TreeNode p1, TreeNode p2) {
//path1和path2分别存储根节点到p1和p2的路径(不包括p1和p2)
List<TreeNode> path1 = new ArrayList<TreeNode>();
List<TreeNode> path2 = new ArrayList<TreeNode>();
List<TreeNode> tmpList = new ArrayList<TreeNode>();

getNodePath(root, p1, tmpList, path1);
getNodePath(root, p2, tmpList, path2);
//如果路径不存在,返回空
if (path1.size() == 0 || path2.size() == 0)
return null;

return getLastCommonParent(path1, path2);
}

// 获取根节点到目标节点的路径
public static void getNodePath(TreeNode root, TreeNode target, List<TreeNode> tmpList, List<TreeNode> path) {
//鲁棒性
if (root == null || root == target)
return;
tmpList.add(root);
List<TreeNode> children = root.children;
for (TreeNode node : children) {
if (node == target) {
path.addAll(tmpList);
break;
}
getNodePath(node, target, tmpList, path);
}

tmpList.remove(tmpList.size() - 1);
}
//将问题转化为求链表最后一个共同节点
private static TreeNode getLastCommonParent(List<TreeNode> p1, List<TreeNode> p2) {
TreeNode tmpNode = null;
for (int i = 0; i < p1.size(); i++) {
if (p1.get(i) != p2.get(i))
break;
tmpNode = p1.get(i);
}

return tmpNode;
}

// 节点类
private static class TreeNode {
int val;

List<TreeNode> children = new ArrayList<>();

public TreeNode(int val) {
this.val = val;
}

@Override
public String toString() {
return val + "";
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐