给定一棵二叉树(不是二叉搜索树)和任意数量的关键节点,任务是找到所有关键节点的最小公共祖先。
以下是维基百科对 LCA 的定义:
设 T 是一棵有根树。两个节点 n1 和 n2 之间的最低公共祖先被定义为 T 中同时具有 n1 和 n2 作为后代的最低节点(我们允许一个节点是它自己的后代)。
T 中任意数量节点的 LCA 是距离根最远的节点的共享公共祖先。
示例:在上图中:
LCA of nodes 12, 14, 15 is node 3
LCA of nodes 3, 14, 15 is node 3
LCA of nodes 6, 7, 15 is node 3
LCA of nodes 5, 13, 14, 15 is node 1
LCA of nodes 6, 12 is node 6
方法:
以下是针对任意数量节点的最小公用祖先的简单方法。
- 对于每个节点,计算该节点及其子树的匹配节点数。
- 如果 root 也是匹配节点。
matchingNodes = matchingNodes in left sub-tree + matchingNodes in right sub-tree + 1
- 如果 root 不是匹配的节点。
matchingNodes = matchingNodes in left sub-tree + matchingNodes in right-subtree
- 如果任何节点的匹配节点数等于键数,则将该节点添加到祖先列表中。
- 祖先列表中的第一个节点是所有给定键的最不常见的祖先。
下面是上述方法的实现。
C++14
// C++ implementation to find
// Ancestors of any number of nodes
#include
using namespace std;
// Tree Class
class TreeNode
{
public:
int data;
TreeNode *left, *right;
TreeNode(int value)
{
this->data = value;
this->left = NULL;
this->right = NULL;
}
};
int getKeysCount(TreeNode *root, vector &keyNodes,
int matchingNodes,
vector &ancestors)
{
// Base Case. When root is Null
if (root == NULL)
{
return 0;
}
// Search for left and right subtree
// for matching child Key Node.
matchingNodes += getKeysCount(root->left, keyNodes,
matchingNodes, ancestors) +
getKeysCount(root->right, keyNodes,
matchingNodes, ancestors);
// Condition to check if Root Node
// is also in Key Node
if (find(keyNodes.begin(),
keyNodes.end(), root->data) != keyNodes.end())
{
matchingNodes++;
}
// Condition when matching Nodes is
// equal to the Key Nodes found
if (matchingNodes == keyNodes.size())
{
ancestors.push_back(root);
}
return matchingNodes;
}
// Function to find Least Common
// Ancestors of N number of nodes
TreeNode *lcaOfNodes(TreeNode *root,
vector &keyNodes)
{
// Create a new list for
// capturing all the ancestors
// of the given nodes
vector ancestors;
// Initially there is No Matching Nodes
int matchingNodes = 0;
getKeysCount(root, keyNodes,
matchingNodes, ancestors);
// First Node in the Ancestors list
// is the Least Common Ancestor of
// Given keyNodes
return ancestors[0];
}
// Driver Code
int main()
{
// Creation of Tree
TreeNode *root = new TreeNode(1);
root->left = new TreeNode(2);
root->right = new TreeNode(3);
root->left->left = new TreeNode(4);
root->left->right = new TreeNode(5);
root->right->left = new TreeNode(6);
root->right->right = new TreeNode(7);
root->left->left->left = new TreeNode(8);
root->left->left->right = new TreeNode(9);
root->left->right->left = new TreeNode(10);
root->left->right->right = new TreeNode(11);
root->right->left->left = new TreeNode(12);
root->right->left->right = new TreeNode(13);
root->right->right->left = new TreeNode(14);
root->right->right->right = new TreeNode(15);
// Key Nodes for LCA
vector keyNodes;
keyNodes.push_back(12);
keyNodes.push_back(14);
keyNodes.push_back(15);
cout << lcaOfNodes(root, keyNodes)->data
<< endl;
return 0;
}
// This code is contributed by sanjeev2552
Java
// Java implementation to find
// Ancestors of any number of nodes
import java.util.ArrayList;
// Tree Class
class TreeNode {
int data;
TreeNode left;
TreeNode right;
public TreeNode(int value)
{
this.data = value;
left = right = null;
}
}
public class LCAofAnyNumberOfNodes {
// Function to find Least Common
// Ancestors of N number of nodes
public static TreeNode lcaOfNodes(
TreeNode root,
ArrayList keyNodes)
{
// Create a new list for
// capturing all the ancestors
// of the given nodes
ArrayList ancestors =
new ArrayList();
// Initially there is No Matching Nodes
int matchingNodes = 0;
getKeysCount(root, keyNodes,
matchingNodes, ancestors);
// First Node in the Ancestors list
// is the Least Common Ancestor of
// Given keyNodes
return ancestors.get(0);
}
private static int getKeysCount(
TreeNode root, ArrayList keyNodes,
int matchingNodes,
ArrayList ancestors)
{
// Base Case. When root is Null
if (root == null)
return 0;
// Search for left and right subtree
// for matching child Key Node.
matchingNodes += getKeysCount(root.left,
keyNodes, matchingNodes, ancestors)
+ getKeysCount(root.right,
keyNodes, matchingNodes, ancestors);
// Condition to check if Root Node
// is also in Key Node
if (keyNodes.contains(root.data)){
matchingNodes++;
}
// Condition when matching Nodes is
// equal to the Key Nodes found
if (matchingNodes == keyNodes.size())
ancestors.add(root);
return matchingNodes;
}
// Driver Code
public static void main(String[] args)
{
// Creation of Tree
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right =
new TreeNode(5);
root.right.left =
new TreeNode(6);
root.right.right =
new TreeNode(7);
root.left.left.left =
new TreeNode(8);
root.left.left.right =
new TreeNode(9);
root.left.right.left =
new TreeNode(10);
root.left.right.right =
new TreeNode(11);
root.right.left.left =
new TreeNode(12);
root.right.left.right =
new TreeNode(13);
root.right.right.left =
new TreeNode(14);
root.right.right.right =
new TreeNode(15);
// Key Nodes for LCA
ArrayList keyNodes =
new ArrayList();
keyNodes.add(12);
keyNodes.add(14);
keyNodes.add(15);
System.out.println(
lcaOfNodes(root, keyNodes).data
);
}
}
C#
// C# implementation to find
// Ancestors of any number of nodes
using System;
using System.Collections.Generic;
// Tree Class
class TreeNode {
public int data;
public TreeNode left;
public TreeNode right;
public TreeNode(int value)
{
this.data = value;
left = right = null;
}
}
public class LCAofAnyNumberOfNodes {
// Function to find Least Common
// Ancestors of N number of nodes
static TreeNode lcaOfNodes(
TreeNode root,
List keyNodes)
{
// Create a new list for
// capturing all the ancestors
// of the given nodes
List ancestors =
new List();
// Initially there is No Matching Nodes
int matchingNodes = 0;
getKeysCount(root, keyNodes,
matchingNodes, ancestors);
// First Node in the Ancestors list
// is the Least Common Ancestor of
// Given keyNodes
return ancestors[0];
}
private static int getKeysCount(
TreeNode root, List keyNodes,
int matchingNodes,
List ancestors)
{
// Base Case. When root is Null
if (root == null)
return 0;
// Search for left and right subtree
// for matching child Key Node.
matchingNodes += getKeysCount(root.left,
keyNodes, matchingNodes, ancestors)
+ getKeysCount(root.right,
keyNodes, matchingNodes, ancestors);
// Condition to check if Root Node
// is also in Key Node
if (keyNodes.Contains(root.data)){
matchingNodes++;
}
// Condition when matching Nodes is
// equal to the Key Nodes found
if (matchingNodes == keyNodes.Count)
ancestors.Add(root);
return matchingNodes;
}
// Driver Code
public static void Main(String[] args)
{
// Creation of Tree
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right =
new TreeNode(5);
root.right.left =
new TreeNode(6);
root.right.right =
new TreeNode(7);
root.left.left.left =
new TreeNode(8);
root.left.left.right =
new TreeNode(9);
root.left.right.left =
new TreeNode(10);
root.left.right.right =
new TreeNode(11);
root.right.left.left =
new TreeNode(12);
root.right.left.right =
new TreeNode(13);
root.right.right.left =
new TreeNode(14);
root.right.right.right =
new TreeNode(15);
// Key Nodes for LCA
List keyNodes = new List();
keyNodes.Add(12);
keyNodes.Add(14);
keyNodes.Add(15);
Console.WriteLine(
lcaOfNodes(root, keyNodes).data
);
}
}
// This code is contributed by PrinciRaj1992
Javascript
输出:
3
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。