树中两个结点的最低公共祖先(剑指offer!!!)

面试题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.\n", pNode->m_nValue);

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

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

    printf( "\n");
}

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;
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值