📌  相关文章
📜  二叉树中任意数量节点的最小公祖

📅  最后修改于: 2021-04-24 18:39:35             🧑  作者: Mango

给定一棵二叉树(不是二叉搜索树)和任意数量的关键节点,任务是找到所有关键节点中最不常见的祖先。

以下是维基百科中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也是一个匹配节点。
  • 如果root不是匹配的节点。
  • 如果在任何节点上匹配的节点数等于键数,则将该节点添加到“祖先”列表中。
  • 祖先列表中的第一个节点是所有给定键的最小公祖。

下面是上述方法的实现。

C++14
// C++ imlementation 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;
     
    // Intially 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 imlementation 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();
         
        // Intially 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# imlementation 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();
          
        // Intially 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


输出:
3