zoukankan      html  css  js  c++  java
  • 【面试题050】树中两个结点的最低公共祖先

    【面试题050】树中两个结点的最低公共祖先
    题目:
        树中两个节点的最低公共祖先。
     
    思路一:
        输入两个树节点,求他们的最低公共祖先,
    ——如果是二叉树,而且是二叉搜索树,那么是可以找到公共节点的。
    二叉搜索树都是排序过的,位于左子树的节点都比父节点小,而位于右子树上面的节点都比父节点大。
    • 如果当前节点的值比两个结点 的值都大,那么最低的共同的父节点一定是在当前节点的左子树中,于是下一步遍历当前节点的左子节点。
    • 如果当前节点的值比两个结点的值都小,那么最低的共同的父节点一定是在当前节点的右子树中,于是下一步遍历当前节点的右子节点。
    • 这样从上到下,找到的第一个在两个输入结点的值之间的节点,就是最低的公共祖先。
     
    思路二:
        如果这棵树不是二叉搜索树,甚至连二叉树都不是,而只是普通的树。
    ——如果有指向父节点的指针,那么这个题目转换成了求,两个双向链表的第一个公共结点的问题。
     
     
    思路三:
        这棵树是普通的树,而且这个树中的结点没有指向父节点的指针。
    ——遍历这个树,看以这个节点为根的子树是否包含这两个节点,如果包含,判断这个节点的子节点是否包含,
    ——知道子节点都不包含而这个当前的节点包含,那么这个节点就是最低的公共祖先。
    ps.这里存在大量的重复遍历,效率不高。
     
    思路三:
        这棵树是普通的树,而且这个树中的结点没有指向父节点的指针。
    ——用两个链表分别保存从根节点到输入的两个结点的路径,然后把问题转换成两个链表的最后公共节点。
     
     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
     
    #include <iostream>
    #include <list>
    #include <vector>
    #include "Tree.h"

    using namespace std;

    bool GetNodePath(TreeNode *pRoot,
                     TreeNode *pNode, list<TreeNode *> &path)
    {
        if (pRoot == pNode)
        {
            return true;
        }
        path.push_back(pRoot);

        bool found = false;

        vector<TreeNode *>::iterator i = pRoot->m_vChildren.begin();
        while (!found
                && i < pRoot->m_vChildren.end())
        {
            found = GetNodePath(*i, pNode, path);
            ++i;
        }
        if (!found)
        {
            path.pop_back();
        }
        return found;
    }


    TreeNode *GetLastCommonNode
    (
        const list<TreeNode *> &path1,
        const list<TreeNode *> &path2
    )
    {
        list<TreeNode *>::const_iterator iterator1 = path1.begin();
        list<TreeNode *>::const_iterator iterator2 = path2.begin();

        TreeNode *pLast = NULL;
        while (iterator1 != path1.end() && iterator2 != path2.end())
        {
            if (*iterator1 == *iterator2)
            {
                pLast = *iterator1;
            }
            iterator1++;
            iterator2++;
        }
        return pLast;
    }

    TreeNode *GetLastCommonParent(TreeNode *pRoot,
                                  TreeNode *pNode1, TreeNode *pNode2)
    {
        if (pRoot == NULL || pNode1 == NULL || pNode2 == NULL)
        {
            return NULL;
        }
        list<TreeNode *> path1;
        GetNodePath(pRoot, pNode1, path1);

        list<TreeNode *> path2;
        GetNodePath(pRoot, pNode2, path2);

        return GetLastCommonNode(path1, path2);
    }


    // 形状普通的树
    //              1
    //            /   
    //           2     3
    //       /       
    //      4         5
    //     /       / |  
    //    6   7    8  9  10
    int main()
    {
        TreeNode *pNode1 = CreateTreeNode(1);
        TreeNode *pNode2 = CreateTreeNode(2);
        TreeNode *pNode3 = CreateTreeNode(3);
        TreeNode *pNode4 = CreateTreeNode(4);
        TreeNode *pNode5 = CreateTreeNode(5);
        TreeNode *pNode6 = CreateTreeNode(6);
        TreeNode *pNode7 = CreateTreeNode(7);
        TreeNode *pNode8 = CreateTreeNode(8);
        TreeNode *pNode9 = CreateTreeNode(9);
        TreeNode *pNode10 = CreateTreeNode(10);

        ConnectTreeNodes(pNode1, pNode2);
        ConnectTreeNodes(pNode1, pNode3);

        ConnectTreeNodes(pNode2, pNode4);
        ConnectTreeNodes(pNode2, pNode5);

        ConnectTreeNodes(pNode4, pNode6);
        ConnectTreeNodes(pNode4, pNode7);

        ConnectTreeNodes(pNode5, pNode8);
        ConnectTreeNodes(pNode5, pNode9);
        ConnectTreeNodes(pNode5, pNode10);


        TreeNode *pRoot = pNode1;
        TreeNode *Node1 = pNode6;
        TreeNode *Node2 =  pNode8;

        TreeNode *pResult =
            GetLastCommonParent(pRoot, Node1, Node2);
        cout << pResult->m_nValue << endl; //输出2
        return 0;
    }
     
    Tree.h:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    #ifndef _TREE_H_
    #define _TREE_H_

    #include <vector>

    struct TreeNode
    {
        int                    m_nValue;
        std::vector<TreeNode *>    m_vChildren;
    };

    TreeNode *CreateTreeNode(int value);
    void ConnectTreeNodes(
        TreeNode *pParent, TreeNode *pChild);
    void PrintTreeNode(TreeNode *pNode);
    void PrintTree(TreeNode *pRoot);
    void DestroyTree(TreeNode *pRoot);


    #endif //_TREE_H_
     
     
    Tree.cpp:
     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
     
    #include "Tree.h"

    TreeNode *CreateTreeNode(int value)
    {
        TreeNode *pNode = new TreeNode();
        pNode->m_nValue = value;

        return pNode;
    }

    void ConnectTreeNodes(TreeNode *pParent, TreeNode *pChild)
    {
        if(pParent != NULL)
        {
            pParent->m_vChildren.push_back(pChild);
        }
    }

    void PrintTreeNode(TreeNode *pNode)
    {
        if(pNode != NULL)
        {
            printf("value of this node is: %d. ", pNode->m_nValue);

            printf("its children is as the following: ");
            std::vector<TreeNode *>::iterator i = pNode->m_vChildren.begin();
            while(i < pNode->m_vChildren.end())
            {
                if(*i != NULL)
                    printf("%d ", (*i)->m_nValue);
            }

            printf(" ");
        }
        else
        {
            printf("this node is null. ");
        }

        printf(" ");
    }

    void PrintTree(TreeNode *pRoot)
    {
        PrintTreeNode(pRoot);

        if(pRoot != NULL)
        {
            std::vector<TreeNode *>::iterator i = pRoot->m_vChildren.begin();
            while(i < pRoot->m_vChildren.end())
            {
                PrintTree(*i);
                ++i;
            }
        }
    }

    void DestroyTree(TreeNode *pRoot)
    {
        if(pRoot != NULL)
        {
            std::vector<TreeNode *>::iterator i = pRoot->m_vChildren.begin();
            while(i < pRoot->m_vChildren.end())
            {
                DestroyTree(*i);
                ++i;
            }

            delete pRoot;
        }
    }
     
     
     
  • 相关阅读:
    ceil函数 floor函数 floor函数 round函数 取整函数
    Havel–Hakimi algorithm(判断度数序列是否可图)
    最小费用最大流
    数论 (大数,小费马定理,欧拉定理,威尔逊定理,快速数论变换(NNT)模版)
    Give Candies(费马小定理)
    Yet Another Crosses Problem
    并查集
    杭电多校第一场-M-Code
    2018ICPC赛后总结
    营业额统计
  • 原文地址:https://www.cnblogs.com/codemylife/p/3776060.html
Copyright © 2011-2022 走看看