📌  相关文章
📜  N叉树中两个给定节点之间的最小距离

📅  最后修改于: 2022-05-13 01:57:16.456000             🧑  作者: Mango

N叉树中两个给定节点之间的最小距离

给定一棵由N个节点组成的 N ary Tree,任务是找到树的节点A到节点B的最小距离。

例子

方法:这个问题可以通过使用LCA (Lowest Common Ancestor)的概念来解决。两个给定节点AB之间的最小距离可以通过使用公式找到 -
mindistance(A, B) = dist (LCA, A) + dist (LCA, B)
请按照以下步骤解决问题:

  1. 分别找到从根节点到节点AB的路径,并将两条路径同时存储在两个数组中。
  2. 现在迭代直到两个数组的值相同并且不匹配之前的值是LCA节点值。
  3. 不匹配之前的值是LCA节点值。
  4. 找到从LCA节点到节点AB的距离,可以通过给定的步骤找到:
    • 在第一个数组中,从LCA节点值迭代并增加计数,直到找到节点A的值,即dist (LCA, A)。
    • 在第二个数组中,从LCA节点值开始迭代并增加计数,直到找到节点 B 的值,即dist (LCA, B)
  5. 返回这些距离的总和,即dist (LCA, A) + dist (LCA, B)
C++
// C++ program for the above approach
#include 
using namespace std;
 
// Structure of Node
struct Node {
    int val;
    vector child;
};
 
// Utility function to create a
// new tree node
Node* newNode(int key)
{
    Node* temp = new Node;
    temp->val = key;
    return temp;
}
 
bool flag;
 
// Function to get the path
// from root to a node
void findPath(Node* root, int key,
              vector& arr)
{
    if (!root)
        return;
    arr.push_back(root->val);
    // if key is found set flag and return
    if (root->val == key) {
        flag = 1;
        return;
    }
    // recur for all children
    for (int i = 0; i < root->child.size(); i++) {
 
        findPath(root->child[i], key, arr);
 
        // if key is found dont need to pop values
        if (flag == 1)
            return;
    }
 
    arr.pop_back();
    return;
}
 
void findMinDist(Node* root, int A, int B)
{
    if (root == NULL)
        return;
    int val = root->val;
 
    // vector to store both paths
    vector arr1, arr2;
 
    // set flag as false;
    flag = false;
 
    // find path from root to node a
    findPath(root, A, arr1);
 
    // set flag again as false;
    flag = false;
 
    // find path from root to node b
    findPath(root, B, arr2);
 
    // to store index of LCA node
    int j;
 
    // if unequal values are found
    // return previous value
    for (int i = 1; i < min(arr1.size(), arr2.size()); i++) {
        if (arr1[i] != arr2[i]) {
            val = arr1[i - 1];
            j = i - 1;
            break;
        }
    }
    int d1 = 0, d2 = 0;
 
    // iterate for finding distance
    // between LCA(a, b) and a
    for (int i = j; i < arr1.size(); i++)
        if (arr1[i] == A)
            break;
        else
            d1 += 1;
 
    // iterate for finding distance
    // between LCA(a, b) and b
    for (int i = j; i < arr2.size(); i++)
        if (arr2[i] == B)
            break;
        else
            d2 += 1;
    // get distance
    val = d1 + d2;
    cout << val << '\n';
}
 
// Driver Code
int main()
 
{
    Node* root = newNode(1);
    (root->child).push_back(newNode(2));
    (root->child).push_back(newNode(3));
    (root->child[0]->child).push_back(newNode(4));
    (root->child[0]->child).push_back(newNode(5));
    (root->child[1]->child).push_back(newNode(6));
    (root->child[1])->child.push_back(newNode(7));
    (root->child[1]->child).push_back(newNode(8));
    int A = 4, B = 3;
 
    // get min distance
    findMinDist(root, A, B);
 
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
public class Main
{
    // Structure of Node
    static class Node {
         
        public int val;
        public Node left, right;
        public Vector child;
         
        public Node(int key)
        {
            val = key;
            left = right = null;
            child = new Vector();
        }
    }
     
    // Utility function to create a
    // new tree node
    static Node newNode(int key)
    {
        Node temp = new Node(key);
        return temp;
    }
      
    static int flag;
      
    // Function to get the path
    // from root to a node
    static void findPath(Node root, int key,
                  Vector arr)
    {
        if (root==null)
            return;
        arr.add(root.val);
        // if key is found set flag and return
        if (root.val == key) {
            flag = 1;
            return;
        }
        // recur for all children
        for (int i = 0; i < root.child.size(); i++) {
      
            findPath(root.child.get(i), key, arr);
      
            // if key is found dont need to pop values
            if (flag == 1)
                return;
        }
      
        arr.remove(arr.size()-1);
        return;
    }
      
    static void findMinDist(Node root, int A, int B)
    {
        if (root == null)
            return;
        int val = root.val;
      
        // vector to store both paths
        Vector arr1 = new Vector();
        Vector arr2 = new Vector();
      
        // set flag as false;
        flag = 0;
      
        // find path from root to node a
        findPath(root, A, arr1);
      
        // set flag again as false;
        flag = 0;
      
        // find path from root to node b
        findPath(root, B, arr2);
      
        // to store index of LCA node
        int j=0;
      
        // if unequal values are found
        // return previous value
        for (int i = 1; i < Math.min(arr1.size(), arr2.size()); i++) {
            if (arr1.get(i) != arr2.get(i)) {
                val = arr1.get(i - 1);
                j = i - 1;
                break;
            }
        }
        int d1 = 0, d2 = 0;
      
        // iterate for finding distance
        // between LCA(a, b) and a
        for (int i = j; i < arr1.size(); i++)
            if (arr1.get(i) == A)
                break;
            else
                d1 += 1;
      
        // iterate for finding distance
        // between LCA(a, b) and b
        for (int i = j; i < arr2.size(); i++)
            if (arr2.get(i) == B)
                break;
            else
                d2 += 1;
        // get distance
        val = d1 + d2;
        System.out.println(val);
    }
     
    public static void main(String[] args) {
        Node root = newNode(1);
        (root.child).add(newNode(2));
        (root.child).add(newNode(3));
        (root.child.get(0).child).add(newNode(4));
        (root.child.get(0).child).add(newNode(5));
        (root.child.get(1).child).add(newNode(6));
        (root.child.get(1)).child.add(newNode(7));
        (root.child.get(1).child).add(newNode(8));
        int A = 4, B = 3;
      
        // get min distance
        findMinDist(root, A, B);
    }
}
 
// This code is contributed by mukesh07.


Python3
# Python3 program for the above approach
 
# Structure of Node
class Node:
    def __init__(self, key):
        self.val = key
        self.left = None
        self.right = None
        self.child = []
 
# Utility function to create a
# new tree node
def newNode(key):
    temp = Node(key)
    return temp
 
flag = 0
 
# Function to get the path
# from root to a node
def findPath(root, key, arr):
    global flag
    if (root==None):
        return
    arr.append(root.val)
    # if key is found set flag and return
    if (root.val == key):
        flag = 1
        return
    # recur for all children
    for i in range(len(root.child)):
        findPath(root.child[i], key, arr)
 
        # if key is found dont need to pop values
        if (flag == 1):
            return
 
    arr.pop()
    return
 
def findMinDist(root, A, B):
    global flag
    if (root == None):
        return
    val = root.val
 
    # vector to store both paths
    arr1 = []
    arr2 = []
 
    # set flag as false;
    flag = 0
 
    # find path from root to node a
    findPath(root, A, arr1)
 
    # set flag again as false;
    flag = 0
 
    # find path from root to node b
    findPath(root, B, arr2)
 
    # to store index of LCA node
    j=0
 
    # if unequal values are found
    # return previous value
    for i in range(min(len(arr1), len(arr2))):
        if (arr1[i] != arr2[i]):
            val = arr1[i - 1]
            j = i - 1
            break
    d1, d2 = 0, 0
 
    # iterate for finding distance
    # between LCA(a, b) and a
    for i in range(j, len(arr1)):
        if (arr1[i] == A):
            break
        else:
            d1 += 1
 
    # iterate for finding distance
    # between LCA(a, b) and b
    for i in range(j, len(arr2)):
        if (arr2[i] == B):
            break
        else:
            d2 += 1
    # get distance
    val = d1 + d2
    print(val)
 
root = newNode(1)
(root.child).append(newNode(2))
(root.child).append(newNode(3))
(root.child[0].child).append(newNode(4))
(root.child[0].child).append(newNode(5))
(root.child[1].child).append(newNode(6))
(root.child[1]).child.append(newNode(7))
(root.child[1].child).append(newNode(8))
A, B = 4, 3
 
# get min distance
findMinDist(root, A, B)
 
# This code is contributed by rameshtravel07.


C#
// C# program for the above approach
using System;
using System.Collections.Generic;
 
// Structure of Node
class GFG{
 
    public class Node {
        public int val;
        public Node left=null, right=null;
        public List child = new List();
    }
 
// Utility function to create a
// new tree node
static Node newNode(int key)
{
    Node temp = new Node();
    temp.val = key;
    return temp;
}
 
static int flag;
 
// Function to get the path
// from root to a node
static void findPath(Node root, int key,
              List arr)
{
    if (root==null)
        return;
    arr.Add(root.val);
    // if key is found set flag and return
    if (root.val == key) {
        flag = 1;
        return;
    }
    // recur for all children
    for (int i = 0; i < root.child.Count; i++) {
 
        findPath(root.child[i], key, arr);
 
        // if key is found dont need to pop values
        if (flag == 1)
            return;
    }
 
    arr.RemoveAt(arr.Count-1);
    return;
}
 
static void findMinDist(Node root, int A, int B)
{
    if (root == null)
        return;
    int val = root.val;
 
    // vector to store both paths
    List arr1 = new List();
    List arr2 = new List();
 
    // set flag as false;
    flag = 0;
 
    // find path from root to node a
    findPath(root, A, arr1);
 
    // set flag again as false;
    flag = 0;
 
    // find path from root to node b
    findPath(root, B, arr2);
 
    // to store index of LCA node
    int j=0;
 
    // if unequal values are found
    // return previous value
    for (int i = 1; i < Math.Min(arr1.Count, arr2.Count); i++) {
        if (arr1[i] != arr2[i]) {
            val = arr1[i - 1];
            j = i - 1;
            break;
        }
    }
    int d1 = 0, d2 = 0;
 
    // iterate for finding distance
    // between LCA(a, b) and a
    for (int i = j; i < arr1.Count; i++)
        if (arr1[i] == A)
            break;
        else
            d1 += 1;
 
    // iterate for finding distance
    // between LCA(a, b) and b
    for (int i = j; i < arr2.Count; i++)
        if (arr2[i] == B)
            break;
        else
            d2 += 1;
    // get distance
    val = d1 + d2;
    Console.WriteLine(val);
}
 
// Driver Code
public static void Main()
 
{
    Node root = newNode(1);
    (root.child).Add(newNode(2));
    (root.child).Add(newNode(3));
    (root.child[0].child).Add(newNode(4));
    (root.child[0].child).Add(newNode(5));
    (root.child[1].child).Add(newNode(6));
    (root.child[1]).child.Add(newNode(7));
    (root.child[1].child).Add(newNode(8));
    int A = 4, B = 3;
 
    // get min distance
    findMinDist(root, A, B);
}
}
 
// This code is contributed by SURENDRA_GANGWAR.


Javascript


输出
3

时间复杂度: O(N)。
辅助空间: O(N)。