求解二叉树中两个节点的最近公共祖先(LCA)

/************************************************************************/
/*
非递归的方法

下面是一个简单的复杂度为 O(n) 的算法,解决LCA问题

1) 找到从根到n1的路径,并存储在一个向量或数组中。
2)找到从根到n2的路径,并存储在一个向量或数组中。
3) 遍历这两条路径,直到遇到一个不同的节点,则前面的那个即为最低公共祖先.

*/
/************************************************************************/

//二叉树节点
struct Node
{
	int key;
	Node *left, *right;
};

//找到从root到 节点值为key的路径,存储在path中。没有的话返回-1
bool findpath(Node * root,vector<int> &path,int key)
{
	if(root == NULL) return false;
	path.push_back(root->key);
	if(root->key == key) return true;
	//左子树或右子树 是否找到,找到的话当前节点就在路径中了
	bool find =  ( findpath(root->left, path, key) || findpath(root->right,path ,key) );
	if(find) return true;
	//该节点下未找到就弹出
	path.pop_back();
	return false;
}

int findLCA(Node * root,int key1,int key2)
{
	vector<int> path1,path2;
	bool find1 = findpath(root, path1, key1);
	bool find2 = findpath(root, path2, key2);
	if(find1 && find2)
	{
		int ans ;
		for(int i=0; i < path1.size(); i++)
		{
			if(path1[i] != path2[i])
			{
				break;
			}
			else
			{
				ans = path1[i];
			}
		}
		return ans;
	}
	return -1;
}

/************************************************************************/
/*
递归求解方法

从root开始遍历,如果n1和n2中的任一个和root匹配,那么root就是LCA。
如果都不匹配,则分别递归左、右子树,
如果有一个 key(n1或n2)出现在左子树,并且另一个key(n1或n2)出现在右子树,则root就是LCA.
如果两个key都出现在左子树,则说明LCA在左子树中,否则在右子树。
*/
/************************************************************************/

struct Node
{
	struct Node *left, *right;
	int key;
};

// 返回n1和n2的 LCA的指针
// 假设n1和n2都出现在树中
struct Node *findLCA(struct Node* root, int n1, int n2)
{
	if (root == NULL) return NULL;

	// 只要n1 或 n2 的任一个匹配即可
	//  (注意:如果 一个节点是另一个祖先,则返回的是祖先节点。因为递归是要返回到祖先的 )
	if (root->key == n1 || root->key == n2)
		return root;
	// 分别在左右子树查找
	Node *left_lca  = findLCA(root->left, n1, n2);
	Node *right_lca = findLCA(root->right, n1, n2);
	// 如果都返回非空指针 Non-NULL, 则说明两个节点分别出现了在两个子树中,则当前节点肯定为LCA
	if (left_lca && right_lca)  return root;
	// 如果一个为空,在说明LCA在另一个子树
	return (left_lca != NULL)? left_lca: right_lca;
}

时间: 2024-10-10 14:24:28

求解二叉树中两个节点的最近公共祖先(LCA)的相关文章

二叉树中两个节点的最近公共祖先节点

#include <iostream> using namespace std; template<class T> struct BinaryTreeNode {                 BinaryTreeNode< T>(const T& data)                                 :_data( data)                                 ,_left( NULL)         

二叉树中寻找共同节点的最低公共祖先节点

问题:在一棵二叉树中,给定两个节点,求这两个节点的最低的公共祖先节点,如下图中的,节点 6 和 节点 9 的最低公共祖先节点是节点 5. 最容易联想到的是,这个问题似乎与公共子串的问题有关系,如果我们能求出两个节点到根节点的路径,再使用匹配算法得到公共的路径,取这个路径上最后一个节点,即是所求的最低公共祖先节点. 哈夫曼编码启迪了我,我打算使用 0 表示向左走,1 表示向右走.如,101 表示自根节点,走到右孩子 A,再走到 A 的左孩子 B,再走到 B 的右孩子 C .于是,根节点到节点 C

二叉树中两个节点的最近公共父节点

这是京东周六的笔试题目   当时不在状态,现在想来肯定是笔试就被刷掉了,权当做个纪念吧.  这个问题可以分为三种情况来考虑: 情况一:root未知,但是每个节点都有parent指针此时可以分别从两个节点开始,沿着parent指针走向根节点,得到两个链表,然后求两个链表的第一个公共节点,这个方法很简单,不需要详细解释的. 情况二:节点只有左.右指针,没有parent指针,root已知思路:有两种情况,一是要找的这两个节点(a, b),在要遍历的节点(root)的两侧,那么这个节点就是这两个节点的最

求解二叉树中两个结点的最低公共父结点

一,问题描述 构建一棵二叉树(不一定是二叉查找树),求出该二叉树中某两个结点的最低公共父结点.借用一张图如下: 结点8 和 结点5 的最低公共父结点为 结点2 二,二叉树的构建 与 求二叉树中第K层结点的个数 文章中的第二点:二叉树构建相同 三,求解最低公共父结点的算法实现 有两种思路,一种是通过中序遍历和后序遍历.由于中序遍历是先左子树中的结点,再访问根,再访问右子树中结点,因此这两个结点的公共父结点一定处于这两个结点之间. 如:中序遍历:8, 4, 9, 2, 5, 1, 6, 3, 7  

求二叉树中两个节点的最低公共父节点

必须通过遍历查找一个节点的祖先集合,然后比较两个节点的祖先集合就可以找到最低的那个.这里采用后序遍历,并传入一个栈记录该节点的祖先节点.在每次访问一个节点时,先把这个节点压入栈,然后判断该节点是不是要查找的那个节点,如果是返回.接着查找它的左子树和右子树,当要查找的节点在它的左右子树中则返回.然后判断该节点与栈顶节点是否相同,是则弹出栈顶元素.这是因为相同就代表了在访问它的左右子树时没有添加新的节点,也就是说要查找的那个节点不在它的左右子树中,则该节点也就是不是要查找的节点的祖先. #inclu

二叉树中两个结点最近的公共祖先汇总

一.若二叉树为搜索二叉树 原题链接:https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/#/description Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST. According to the definition of LCA on

剑指offer-树中两个节点的最低公共祖先

普通二叉树 /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q)

求树中两个节点的最低公共祖先

情形1:树是搜索二叉树 思路:从树的根节点开始遍历,如果根节点的值大于其中一个节点,小于另外一个节点,则根节点就是最低公共祖先.否则如果根节点的值小于两个节点的值,则递归求根节点的右子树,如果大于两个节点的值则递归求根的左子树.如果根节点正好是其中的一个节点,那么说明这两个节点在一条路径上,所以最低公共祖先则是根节点的父节点 public static BinaryTreeNode getLowestCommonAncestor(BinaryTreeNode rootParent,BinaryT

二叉树中任意两个节点的最近公共祖先节点

1.二叉树是个搜索二叉树 2.二叉树带有指向parent的指针 可转换成两个链表的相交节点 3.普通二叉树 保存从根节点分别到这两个节点的路径到list1和list2中 从list1和list2中找第一个不相等的节点即为最近公共祖先节点 template<class T> BinaryTreeNode<T>*  BinaryTree<T>::lastCommnParent(BinaryTreeNode<T>*& node1, BinaryTreeNo