N叉树中两个给定节点之间的最小距离
给定一棵由N个节点组成的 N ary Tree,任务是找到树的节点A到节点B的最小距离。
例子:
Input:
1
/ \
2 3
/ \ / \ \
4 5 6 7 8
A = 4, B = 3
Output: 3
Explanation: The path 4->2->1->3 gives the minimum distance from A to B.
Input:
1
/ \
2 3
/ \ \
6 7 8
A = 6, B = 7
Output: 2
方法:这个问题可以通过使用LCA (Lowest Common Ancestor)的概念来解决。两个给定节点A和B之间的最小距离可以通过使用公式找到 -
mindistance(A, B) = dist (LCA, A) + dist (LCA, B)
请按照以下步骤解决问题:
- 分别找到从根节点到节点A和B的路径,并将两条路径同时存储在两个数组中。
- 现在迭代直到两个数组的值相同并且不匹配之前的值是LCA节点值。
- 不匹配之前的值是LCA节点值。
- 找到从LCA节点到节点A和B的距离,可以通过给定的步骤找到:
- 在第一个数组中,从LCA节点值迭代并增加计数,直到找到节点A的值,即dist (LCA, A)。
- 在第二个数组中,从LCA节点值开始迭代并增加计数,直到找到节点 B 的值,即dist (LCA, B)
- 返回这些距离的总和,即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)。