劍指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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM