题目

输入二叉树中的两个结点,输出这两个结点在数中最低的共同父结点。

二叉树的结点定义如下:

 C++ Code 
1
2
3
4
5
6
 
struct BinaryTreeNode
{
    int value;
    BinaryTreeNode *left;
    BinaryTreeNode *right;
};

【分析】

求数中两个结点的最低共同结点是面试中经常出现的一个问题。这个问题有几个变种。

【变种1】

第一个变种是二叉树是一种特殊的二叉树:查找二叉树。也就是树是排序过的,位于左子树上的结点都比父结点小,而位于右子树的结点都比父结点大。我们只需要从根结点开始和两个结点进行比较。如果当前结点的值比两个结点都大,则最低的共同父结点一定在当前结点的左子树中。如果当前结点的值比两个结点都小,则最低的共同父结点一定在当前结点的右子树中。

具体代码如下:

 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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
 
// 48_GetLowestCommonAncessor.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

struct BinaryTreeNode
{
    int value;
    BinaryTreeNode *left;
    BinaryTreeNode *right;
};

BinaryTreeNode* create_tree_r(int a[],int left,int right)
{
    // base case for leaf-node
    if (left>right)
        return NULL;
    ;
    BinaryTreeNode *root = new BinaryTreeNode();
    root->value = a[mid];
    if(left<=mid)
        root->left = create_tree_r(a,left,mid-);
    if (right>=mid)
        root->right = create_tree_r(a,mid+,right);
    return root;
}

BinaryTreeNode* CreateTree(int a[],int length)
{
    )
        return NULL;
    );
}

// whether tree root has node x?
bool HasNode(BinaryTreeNode *root,int x)
{
    if(NULL==root)
        return false;
    if (root->value==x)
    {
        return true;
    }
    else if (root->value<x)
    {
        return HasNode(root->right,x);
    }
    else 
    {
        return HasNode(root->left,x);
    }
}

// check whether root tree has node
bool HasNode(BinaryTreeNode *root,BinaryTreeNode *node)
{
    if (root==node)
        return true;
    bool bLeft = false;
    bool bRight = false;
    // check in left sub-tree
    if (root->left!=NULL)
        bLeft = HasNode(root->left,node);

// check in left right-tree
    if (root->right!=NULL)
        bRight = HasNode(root->right,node);
    return bLeft||bRight;
}

// get lowest common ancestor recursively
BinaryTreeNode* GetLowestCommonAncestor_Recursively(BinaryTreeNode *root,int x,int y)
{
    if(NULL==root)
        return NULL;
    if(root->value>=x && root->value<=y)
    {// x in left and y in right sub-tree
        return root;
    }
    else if (root->value<x)
    {// x y in right sub-tree
        return GetLowestCommonAncestor_Recursively(root->right,x,y);
    }
    else
    //else if(root->value>y)
    {// x y in left sub-tree 
        return GetLowestCommonAncestor_Recursively(root->left,x,y);
    }
}

// get lowest common ancestor iteratively
BinaryTreeNode* GetLowestCommonAncestor_Iteratively(BinaryTreeNode *root,int x, int y)
{
    if(NULL==root)
        return NULL;
    BinaryTreeNode *cur = root;
    while(cur!=NULL)
    {
        if(cur->value>=x && cur->value<=y)
        {// x in left and y in right sub-tree
            return cur;
        }
        else if (cur->value<x)
        {// x y in right sub-tree
            cur = cur->right;
        }
        else 
        {// x y in left sub-tree 
            cur = cur->left;
        }
    }
    return cur;
}

// get lca for x and y 
BinaryTreeNode* GetLCA_Solution(BinaryTreeNode *root,int x,int y)
{
    // check whether root has x and y
    if (HasNode(root,x)&&HasNode(root,y))
        return GetLowestCommonAncestor_Iteratively(root,x,y);
    else 
        return NULL;
}

void test_base(BinaryTreeNode *root,int x,int y)
{
    BinaryTreeNode *result = GetLCA_Solution(root,x,y);
    if (NULL==result)
    {
        printf("%s\n","can not find lca.");
    }
    else
    {
        printf("%d,%d--->%d\n",x,y,result->value);
    }
}

void test_case()
{
    /*
                 5
                /\
               /  \
              /    \
             2     7
            / \   / \
           /  |   |  \
          1   3  6  8
                \        \
                4         9
    */
    };
    int length = sizeof(a)/sizeof(int);
    BinaryTreeNode *root = CreateTree(a,length);
    test_base(root,); // 5
); // 2
); // 7
    // special case
); // cannot find lca
);// cannot find lca
}

int _tmain(int argc, _TCHAR* argv[])
{
    test_case();
    ;
}
/*
4,9--->5
1,4--->2
6,9--->7
can not find lca.
can not find lca.
*/

【变种2】

第二个变种是树为多叉树,每个结点都有一个指针指向它的父结点。于是我们可以从任何一个结点出发,得到一个到达树根结点的单向链表。因此这个问题转换为两个单向链表的第一个公共结点,之前35.两链表的第一个公共结点已经讨论过。

【变种3】

第三个变种是树为多叉树,每个父节点有若干个子节点,但是子节点没有指向父节点指针。我们只能从根节点遍历树,从而得到从根节点到某一节点的路径,然后求这两个路径的最后一个公共节点

本题中的二叉树是第三个变种的一个特例,即每个父节点只有左右子节点。

具体代码如下:

 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
 
#include <vector>
#include <iostream>
using namespace std;

// treenode
struct TreeNode
{
    int value;
    vector<TreeNode*> vChildren;
};

// get tree node path from root to node
bool GetNodePath(TreeNode *root,TreeNode *node,vector<TreeNode*> &path)
{
    if(root==node)
        return true;
    path.push_back(root);
    // find node in root's children
    bool found = false;
    vector<TreeNode*>::iterator iter = root->vChildren.begin();
    while(!found&&iter<root->vChildren.end())
    {
        found = GetNodePath(*iter,node,path);
        iter++;
    }
    // if not found in root's children,then remove it from path
    if (!found)
        path.pop_back();
    return found;
}

// get last common node of path1 and path2
TreeNode* GetLastCommonNode(const vector<TreeNode*> &path1,const vector<TreeNode*> &path2)
{// A-B-D, A-B-E
    vector<TreeNode*>::const_iterator iter1= path1.begin();
    vector<TreeNode*>::const_iterator iter2= path2.begin();

TreeNode *lastNode = NULL;
    while(iter1!=path1.end()&&iter2!=path2.end())
    {
        if (*iter1==*iter2)
            lastNode = *iter1;
        iter1++;
        iter2++;
    }
    return lastNode;
}

// get lowest common ancestor 
TreeNode* GetLCA(TreeNode* root,TreeNode *node1,TreeNode *node2)
{// O(n)+O(n)+O(n) = O(n)
    if(NULL==root||NULL==node1||node2==NULL)
        return NULL;
    vector<TreeNode*> path1;
    GetNodePath(root,node1,path1);
    vector<TreeNode*> path2;
    GetNodePath(root,node2,path2);
    return GetLastCommonNode(path1,path2);
}

【参考】

http://zhedahht.blog.163.com/blog/static/25411174201081263815813/

http://blog.csdn.net/dahai_881222/article/details/7801356

http://www.cnblogs.com/venow/archive/2012/08/31/2664969.html

【本文链接】

http://www.cnblogs.com/hellogiser/p/get-lowest-common-ancestor-of-binary-tree.html

48. 二叉树两结点的最低共同父结点(3种变种情况)[Get lowest common ancestor of binary tree]的更多相关文章

  1. Lowest Common Ancestor of a Binary Search Tree(树中两个结点的最低公共祖先)

    题目描述: Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in ...

  2. [LeetCode] Lowest Common Ancestor of a Binary Tree 二叉树的最小共同父节点

    Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According ...

  3. [LeetCode] 1123. Lowest Common Ancestor of Deepest Leaves 最深叶结点的最小公共父节点

    Given a rooted binary tree, return the lowest common ancestor of its deepest leaves. Recall that: Th ...

  4. [LeetCode] 236. Lowest Common Ancestor of a Binary Tree 二叉树的最小共同父节点

    Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According ...

  5. [CareerCup] 4.7 Lowest Common Ancestor of a Binary Search Tree 二叉树的最小共同父节点

    4.7 Design an algorithm and write code to find the first common ancestor of two nodes in a binary tr ...

  6. [Swift]LeetCode236. 二叉树的最近公共祖先 | Lowest Common Ancestor of a Binary Tree

    Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According ...

  7. 51.Lowest Common Ancestor of a Binary Tree(二叉树的最小公共祖先)

    Level:   Medium 题目描述: Given a binary tree, find the lowest common ancestor (LCA) of two given nodes ...

  8. [LeetCode] Lowest Common Ancestor of a Binary Search Tree 二叉搜索树的最小共同父节点

    Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BS ...

  9. [leetcode]236. Lowest Common Ancestor of a Binary Tree二叉树最近公共祖先

      Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. Accordi ...

随机推荐

  1. mtk flash tool,Win7 On VirtualBox

    SP_Flash_Tool_exe_Windows_v5.1624.00.000 Win7 在 VirtualBox, 安裝 mtk flash tool, v5.1628 在燒錄時會 fail. v ...

  2. 在移动端中的flex布局

    flex布局介绍: flex布局很灵活, 这种布局我们也可以称之为弹性布局,  弹性布局的主要优势就是元素的宽或者高会自动补全; flex布局实例: 比如有两个div,一个div的宽度为100px, ...

  3. 关于闭包(closure)的一些概念

    和其他大多数现代编程语言一样,JS也采用词法作用域,也就是说,函数的执行依赖于变量作用域,这个作用域是在函数定义时决定的,而不是函数调用时决定的.为了实现这种词法作用域,JS函数对象的内部状态不仅包含 ...

  4. Bzoj1426 收集邮票

    Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 292  Solved: 232 Description 有n种不同的邮票,皮皮想收集所有种类的邮票.唯一 ...

  5. python学习笔记(二)

    (一)模块打包     --->        注:suba和subb文件夹下的__init__.py文件,即使为空,也必须存在 "setup.py" from distut ...

  6. centos 7.0 编译安装php 7.0.3

    php下载页面 http://cn2.php.net/downloads.php 7.0.3多地区下载页面 http://cn2.php.net/get/php-7.0.3.tar.gz/from/a ...

  7. XSS的防御

    基于代码修改的防御 和SQL注入防御一样,XSS攻击也是利用了Web页面的编写疏忽,所以还有一种方法就是从Web应用开发的角度来避免: 步骤1.对所有用户提交内容进行可靠的输入验证,包括对URL.查询 ...

  8. nginx服务器命令

    nginx -s reload  :修改配置后重新加载生效 nginx -s reopen  :重新打开日志文件nginx -t -c /path/to/nginx.conf 测试nginx配置文件是 ...

  9. 关于JSP中<body onload="fun()">body标签中onload中函数不执行问题

    问题描述: 在一个页面中,我们经常会初始化一下数据,而且会在指定的DOM元素初始化数据,这时候我们就会使用<body onload="fun()">来加载我们的数据.o ...

  10. 3MyBatis配置--深入浅出MyBatis技术原理与实践(笔记)

    XML 映射配置文件 configuration 配置 properties 属性 settings 设置 typeAliases 类型命名 typeHandlers 类型处理器 objectFact ...