|
树中两个结点的最低公共祖先 代码实现:
package case50_GetLastCommonNode;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Stack;
/**
* 题目:输入树的两个结点,求他们的最低公共祖先。
*
* @author WangSai
*
*/
public class GetLastCommonNode {
/**
* 1>:若树是二叉搜索树,则可以根据这个两个结点和二叉搜索的的特点遍历完成。
*
* @param root,二叉树的根节点
* @param node1,二叉树中的指定节点
* @param node2,二叉树中的指定节点
* @return 二叉树中的最低公共祖先
*/
private TreeNode getMyNode1(TreeNode root, TreeNode node1, TreeNode node2) {
// 异常值检测
if (root == null)
return null;
// 递归调用,判断。
// 当树中当前节点的值大于node1和node2的值得时候,最低公共祖先在左子节点中。
if (root.data > node1.data && root.data > node2.data) {
return getMyNode1(root.lchild, node1, node2);
}
// 当树中当前节点的值小于node1和node2的值得时候,最低公共祖先在右子节点中。
else if (root.data < node1.data && root.data < node2.data) {
return getMyNode1(root.rchild, node1, node2);
}
// 当树中当前节点的值介于node1和node2的值之间的时候,该节点就是最低公共祖先。
else if ((root.data >= node1.data && root.data <= node2.data)
|| (root.data <= node1.data && root.data >= node2.data)) {
return root;
}
return null;
}
/**
* 2>:若树是普通树,但是有指向父节点的parent指针。这种问题可以转换成求链表的第一个公共节点的问题。
*
* @param root,二叉树的根节点
* @param node1,二叉树中的指定节点
* @param node2,二叉树中的指定节点
* @return 二叉树中的最低公共祖先
*/
private TreeNode getMyNode2(TreeNode root, TreeNode node1, TreeNode node2) {
if (root == null)
return null;
// 创建辅助栈1
Stack<TreeNode> stack1 = new Stack<TreeNode>();
while (node1 != null) {
stack1.push(node1);
node1 = node1.parent;
}
// 创建辅助栈2
Stack<TreeNode> stack2 = new Stack<TreeNode>();
while (node2 != null) {
stack2.push(node2);
node2 = node2.parent;
}
while (stack1.size() > 0 && stack2.size() > 0) {
TreeNode tmp1 = stack1.pop();
TreeNode tmp2 = stack2.pop();
if (tmp2.data == tmp1.data) {
return tmp1;
}
}
return null;
}
/**
* 3>:若树是普通树,没有指向父节点的parent指针。我们可以从头根节点开始遍历,然后把包含node1和node2节点的路径保存下来。然后,
* 可以转换成求链表的第一个公共节点的问题。
*
* @param root,二叉树的根节点
* @param node1,二叉树中的指定节点
* @param node2,二叉树中的指定节点
* @return 二叉树中的最低公共祖先
*/
private static TreeNode getMyNode3(TreeNode root, TreeNode node1, TreeNode node2) {
// 异常值检测
if (root == null)
return null;
// 辅助空间保存包含node1的路径
ArrayList<TreeNode> list1 = new ArrayList<TreeNode>();
// 辅助空间保存包含node2的路径
ArrayList<TreeNode> list2 = new ArrayList<TreeNode>();
// 寻找存在node1在以root为根节点的树中的路径
findPath(root, node1, list1);
// 寻找存在node2在以root为根节点的树中的路径
findPath(root, node2, list2);
// 把list1中保存的节点入栈
Stack<TreeNode> stack1 = new Stack<TreeNode>();
Iterator<TreeNode> ite1 = list1.iterator();
while (ite1.hasNext()) {
stack1.push(ite1.next());
}
// 把list2中保存的节点入栈
Stack<TreeNode> stack2 = new Stack<TreeNode>();
Iterator<TreeNode> ite2 = list2.iterator();
while (ite2.hasNext()) {
stack2.push(ite2.next());
}
while (!stack1.isEmpty() && !stack2.isEmpty()) {
TreeNode n1 = stack1.pop();
TreeNode n2 = stack2.pop();
if (n1 == n2)
return n1;
}
return null;
}
/**
* 以root为根节点的树包含node节点的路径。
*
* @param root,树的根节点
* @param node,树中的节点
* @param list,保存包含node1的路径
*/
private static void findPath(TreeNode root, TreeNode node, ArrayList<TreeNode> list) {
if (root == null)
return;
list.add(root);
if (root != node) {
if (root.lchild == null && root.rchild == null && root.mchild == null) {
list.remove(list.size() - 1);
return;
} else {
findPath(root.lchild, node, list);
for (TreeNode temp : list) {
if (temp == node)
return;
}
findPath(root.rchild, node, list);
for (TreeNode temp : list) {
if (temp == node)
return;
}
findPath(root.mchild, node, list);
for (TreeNode temp : list) {
if (temp == node)
return;
}
list.remove(list.size() - 1);
}
} else if (root == node) {
return;
}
}
public static void main(String[] args) {
test1();
test2();
}
/**
* 普通二叉树
* ..............1..............................................................
* ........../.......\...........................................................
* .........2.........3..........................................................
* ......./..\......./..\.........................................................
* ......4...5......6....7.......................................................
* ...../.../..\......./.|.\....................................................
* ....8...12..9......13.10.11...................................................
*/
private static void test1() {
TreeNode root = 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);
TreeNode n7 = new TreeNode(7);
TreeNode n8 = new TreeNode(8);
TreeNode n9 = new TreeNode(9);
TreeNode n10 = new TreeNode(10);
TreeNode n11 = new TreeNode(11);
TreeNode n12 = new TreeNode(12);
TreeNode n13 = new TreeNode(13);
root.lchild = n2;
root.rchild = n3;
n2.lchild = n4;
n2.rchild = n5;
n3.lchild = n6;
n3.rchild = n7;
n4.lchild = n8;
n5.rchild = n9;
n5.lchild = n12;
n7.rchild = n11;
n7.lchild = n13;
n7.mchild = n10;
System.out.print("普通二叉树,最低公共祖先为 1 :");
TreeNode node1 = getMyNode3(root, n8, n11);
System.out.println(node1.data);
System.out.print("普通树,最低公共祖先为 7 :");
TreeNode node2 = getMyNode3(root, n13, n11);
System.out.println(node2.data);
System.out.print("普通树n11为树中的节点,另一个节点为null,最低公共祖先为 null :");
TreeNode node3 = getMyNode3(root, null, n11);
System.out.println(node3);
}
/**
* 退化二叉树
* ..............1..............................................................
* ........../..................................................................
* .........2...................................................................
* ......./......................................................................
* ......4.......................................................................
* ...../.......................................................................
* ....8.........................................................................
*/
private static void test2() {
TreeNode root = new TreeNode(1);
TreeNode n2 = new TreeNode(2);
TreeNode n4 = new TreeNode(4);
TreeNode n8 = new TreeNode(8);
root.lchild = n2;
n2.lchild = n4;
n2.rchild = n8;
System.out.print("退化为斜树,最低公共祖先为 2 :");
TreeNode node1 = getMyNode3(root, n8, n4);
System.out.println(node1.data);
}
}
树中节点结构的定义:
package case50_GetLastCommonNode;
/**
* 二叉树的节点结构定义
*
* @author WangSai
*
*/
public class TreeNode {
int data;
TreeNode lchild;
TreeNode rchild;
TreeNode mchild;
TreeNode parent;
public TreeNode() {
}
public TreeNode(int data) {
this.data = data;
}
}
|