zoukankan      html  css  js  c++  java
  • 剑指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 }
  • 相关阅读:
    CSS3媒体查询总结
    关于前端学习规划
    开发技术版本
    Visual Studio 问题汇总
    asp.net web core 开发问题汇总(1)
    asp.net web core 部署问题汇总
    报表平台需求文档(V0.0.0.1)
    Git使用说明
    派生类
    cin、cout的重载
  • 原文地址:https://www.cnblogs.com/coderlynn/p/8680692.html
Copyright © 2011-2022 走看看