剑指offer面试题68 ---- 树中两个节点的最低公共祖先(java实现)

LCA(最近公共祖先)

1.树是二叉搜索树

 1 package lca;
 2             
 3 public class BinarySearchTree {
 4     public static void main(String args[]) {
 5         
 6         //放树节点的数组
 7         TreeNode<Integer> node[] = new TreeNode[7];
 8         
 9         //给节点赋值的数组
10         int arr[] = {4,2,6,1,3,5,7};
11         
12         //处理引用关系
13         //从0开始对节点编号的话,第i个节点的左子节点下标为2*i+1,右子节点为2*i+2
14         for(int i=6;i>=0;i--) {
15             node[i] = new TreeNode();
16             node[i].value = arr[i];
17             //不是叶子节点的话(叶子节点没有子节点),把引用指向叶子节点
18             if (i < node.length/2) {
19                 node[i].left = node[2 * i + 1];
20                 node[i].right = node[2 * i + 2];
21             }
22         }
23         /*
24                 4
25                /  \
26               2    6
27              / \  / \
28             1   3 5  7
29          */
30         //找值为3的节点和值为5的节点的LCA
31         TreeNode result = findLCA(node[4],node[5],node[0]);
32         
33         System.out.println(result);    
34     }
35 
36     private static TreeNode findLCA(TreeNode node1, TreeNode node2, TreeNode current) {
37         // TODO Auto-generated method stub
38         //当前节点的值
39         int value = (int) current.value;
40         //比当前节点都小就到左子树中去找
41         if(value > (int)node1.value && value > (int)node2.value ) {
42             return findLCA(node1,node2,current.left);
43         }
44         //比当前节点都大就到左子树中去找
45         if(value < (int)node1.value && value < (int)node2.value ) {
46             return findLCA(node1,node2,current.right);
47         }
48         
49         //否则就是当前节点
50         //***二叉搜索树的定义是左子节点小于等于根节点,右子节点大于等于根节点。
51         //***对于有值相等的情况也是输出当前节点,比如
52         /*
53                7
54               / \
55              7   8
56         */
57         
58         return current;
59     }
60 
61     
62 }
63 
64 class TreeNode<T>{
65     T value;
66     TreeNode left;
67     TreeNode right;
68     @Override
69     public String toString() {
70         return "TreeNode [value=" + value + "]";
71     }
72     
73 }

2.树不是二叉树,但是有指向父节点的引用 ---- 转换为两个链表求公共节点

 

3.树不是二叉树,也没有指向父节点的引用。

思路 : 使用两个链表保存根节点到两个节点的路径,再求公共节点

 1 package lca;
 2 
 3 import java.util.Arrays;
 4 
 5 //树结构定义
 6 public class TreeNode1 {
 7     char value;
 8     TreeNode1 childs[];
 9     @Override
10     public String toString() {
11         return "TreeNode1 [value=" + value + "]";
12     }
13     
14 }

 

  1 package lca;
  2 
  3 import java.util.LinkedList;
  4 
  5 public class WithoutParentNode {
  6     
  7     static final int maxNumOfChilds = 10;
  8     //使用两个链表来保存根节点到所求节点的路径
  9     static LinkedList list1 = new LinkedList();
 10     static LinkedList list2 = new LinkedList();
 11     
 12     public static void main(String args[]) {
 13         TreeNode1 A = new TreeNode1();
 14         A.value = 'A';
 15         TreeNode1 B = new TreeNode1();
 16         B.value = 'B';
 17         TreeNode1 C = new TreeNode1();
 18         C.value = 'C';
 19         TreeNode1 D = new TreeNode1();
 20         D.value = 'D';
 21         TreeNode1 E = new TreeNode1();
 22         E.value = 'E';
 23         TreeNode1 F = new TreeNode1();
 24         F.value = 'F';
 25         TreeNode1 G = new TreeNode1();
 26         G.value = 'G';
 27         TreeNode1 H = new TreeNode1();
 28         H.value = 'H';
 29         TreeNode1 I = new TreeNode1();
 30         I.value = 'I';
 31         TreeNode1 J = new TreeNode1();
 32         J.value = 'J';
 33         A.childs = new TreeNode1[] {B,C};
 34         B.childs = new TreeNode1[] {D,E};
 35         D.childs = new TreeNode1[] {F,G};
 36         E.childs = new TreeNode1[] {H,I,J};
 37         /*
 38                 A
 39                / \ 
 40               B   C
 41              /  \ 
 42              D    E
 43            / \   / | \
 44           F   G  H I  J
 45          */
 46         
 47         //找F,H节点的LCA
 48         TreeNode1 lca = findLCA(F,H,A);
 49         System.out.println(lca);
 50     }
 51     
 52     
 53     private static TreeNode1 findLCA(TreeNode1 node1, TreeNode1 node2, TreeNode1 root) {
 54         // TODO Auto-generated method stub
 55         getPathFromRootToNode(node1,root,list1);
 56         getPathFromRootToNode(node2,root,list2);
 57         //list1 : D -- B -- A
 58         //list2 : E -- B -- A
 59         
 60         //接下来遍历两个链表找到最近的公共节点
 61         int index = 0;
 62         int length1 = list1.size();
 63         int length2 = list2.size();
 64         int sub = length1 > length2?length1-length2:length2-length1;
 65         if(length2 > length1) {
 66             LinkedList temp = list1;
 67             list1 = list2;
 68             list2 = temp;
 69         }
 70         while(index != length2-1) {
 71             if(((TreeNode1)list1.get(index+sub)).value == ((TreeNode1)list2.get(index)).value) {
 72                 return (TreeNode1)list2.get(index);
 73             }else {
 74                 index++;
 75             }
 76         }
 77         return null;
 78     }
 79 
 80 
 81     private static boolean getPathFromRootToNode(TreeNode1 node, TreeNode1 currentRoot, LinkedList list) {
 82         // TODO Auto-generated method stub
 83         
 84         //找到就直接返回true
 85         if(node.value == currentRoot.value) {
 86             return true;
 87         }
 88         
 89         //找不到就将当前节点加入路径,push是在链表的头插入的,offer是尾部
 90         list.push(currentRoot);
 91         
 92         boolean found = false;
 93         
 94         TreeNode1[] childs = currentRoot.childs;
 95         if (childs != null && childs.length > 0) {
 96             //遍历当前节点的所有子节点,在子节点里边找
 97             for (int i = 0; i < childs.length; i++) {
 98                 if (found) {
 99                     break;
100                 } else {
101                     found = getPathFromRootToNode(node, childs[i], list);
102                 }
103             } 
104         }
105         //找不到就将当前节点从路径中删除,因为是递归,当递归回来到这里的时候,当前节点一定是list的最后一个节点,即栈顶
106         if(!found) {
107             list.pop();
108         }
109         
110         return found;
111     }
112     
113     
114 }

 

posted @ 2018-03-31 02:46  CoderLynn  阅读(2213)  评论(0编辑  收藏  举报