给定一棵具有N个节点的根树,任务是为该树的给定节点V找到最低的共同祖先。
例子:
Input:
1
/ | \
2 3 4
/ \ | |
5 6 7 10
/ \
8 9
V[] = {7, 3, 8, 9}
Output: 3
Input:
1
/ | \
2 3 4
/ \ | |
5 6 7 10
/ \
8 9
V[] = {4, 6, 7}
Output: 1
方法:我们可以观察到
- 任何节点集的最低公共祖先的入时时间将小于或等于该集合中所有节点的时间,而离任时间大于或等于(如果该集合中存在LCA,则等于)。集合。
- 因此,为了解决该问题,我们需要使用深度优先搜索遍历从根节点开始遍历整个树,并存储每个节点的及时,不及时和级别。
- 答案是in-in时间小于或等于集合中的所有节点,out-time大于或等于集合中的所有节点的节点。
下面是上述方法的实现:
C++
// C++ Program to find the LCA
// in a rooted tree for a given
// set of nodes
#include
using namespace std;
// Set time 1 initially
int T = 1;
void dfs(int node, int parent,
vector g[],
int level[], int t_in[],
int t_out[])
{
// Case for root node
if (parent == -1) {
level[node] = 1;
}
else {
level[node] = level[parent] + 1;
}
// In-time for node
t_in[node] = T;
for (auto i : g[node]) {
if (i != parent) {
T++;
dfs(i, node, g,
level, t_in, t_out);
}
}
T++;
// Out-time for the node
t_out[node] = T;
}
int findLCA(int n, vector g[],
vector v)
{
// level[i]--> Level of node i
int level[n + 1];
// t_in[i]--> In-time of node i
int t_in[n + 1];
// t_out[i]--> Out-time of node i
int t_out[n + 1];
// Fill the level, in-time
// and out-time of all nodes
dfs(1, -1, g,
level, t_in, t_out);
int mint = INT_MAX, maxt = INT_MIN;
int minv = -1, maxv = -1;
for (auto i = v.begin(); i != v.end(); i++) {
// To find minimum in-time among
// all nodes in LCA set
if (t_in[*i] < mint) {
mint = t_in[*i];
minv = *i;
}
// To find maximum in-time among
// all nodes in LCA set
if (t_out[*i] > maxt) {
maxt = t_out[*i];
maxv = *i;
}
}
// Node with same minimum
// and maximum out time
// is LCA for the set
if (minv == maxv) {
return minv;
}
// Take the minimum level as level of LCA
int lev = min(level[minv], level[maxv]);
int node, l = INT_MIN;
for (int i = 1; i <= n; i++) {
// If i-th node is at a higher level
// than that of the minimum among
// the nodes of the given set
if (level[i] > lev)
continue;
// Compare in-time, out-time
// and level of i-th node
// to the respective extremes
// among all nodes of the given set
if (t_in[i] <= mint
&& t_out[i] >= maxt
&& level[i] > l) {
node = i;
l = level[i];
}
}
return node;
}
// Driver code
int main()
{
int n = 10;
vector g[n + 1];
g[1].push_back(2);
g[2].push_back(1);
g[1].push_back(3);
g[3].push_back(1);
g[1].push_back(4);
g[4].push_back(1);
g[2].push_back(5);
g[5].push_back(2);
g[2].push_back(6);
g[6].push_back(2);
g[3].push_back(7);
g[7].push_back(3);
g[4].push_back(10);
g[10].push_back(4);
g[8].push_back(7);
g[7].push_back(8);
g[9].push_back(7);
g[7].push_back(9);
vector v = { 7, 3, 8 };
cout << findLCA(n, g, v) << endl;
}
Java
// Java Program to find the LCA
// in a rooted tree for a given
// set of nodes
import java.util.*;
class GFG
{
// Set time 1 initially
static int T = 1;
static void dfs(int node, int parent,
Vector g[],
int level[], int t_in[],
int t_out[])
{
// Case for root node
if (parent == -1)
{
level[node] = 1;
}
else
{
level[node] = level[parent] + 1;
}
// In-time for node
t_in[node] = T;
for (int i : g[node])
{
if (i != parent)
{
T++;
dfs(i, node, g,
level, t_in, t_out);
}
}
T++;
// Out-time for the node
t_out[node] = T;
}
static int findLCA(int n, Vector g[],
Vector v)
{
// level[i]-. Level of node i
int []level = new int[n + 1];
// t_in[i]-. In-time of node i
int []t_in = new int[n + 1];
// t_out[i]-. Out-time of node i
int []t_out = new int[n + 1];
// Fill the level, in-time
// and out-time of all nodes
dfs(1, -1, g,
level, t_in, t_out);
int mint = Integer.MAX_VALUE, maxt = Integer.MIN_VALUE;
int minv = -1, maxv = -1;
for (int i =0; i maxt)
{
maxt = t_out[v.get(i)];
maxv = v.get(i);
}
}
// Node with same minimum
// and maximum out time
// is LCA for the set
if (minv == maxv)
{
return minv;
}
// Take the minimum level as level of LCA
int lev = Math.min(level[minv], level[maxv]);
int node = 0, l = Integer.MIN_VALUE;
for (int i = 1; i <= n; i++)
{
// If i-th node is at a higher level
// than that of the minimum among
// the nodes of the given set
if (level[i] > lev)
continue;
// Compare in-time, out-time
// and level of i-th node
// to the respective extremes
// among all nodes of the given set
if (t_in[i] <= mint
&& t_out[i] >= maxt
&& level[i] > l)
{
node = i;
l = level[i];
}
}
return node;
}
// Driver code
public static void main(String[] args)
{
int n = 10;
Vector []g = new Vector[n + 1];
for (int i = 0; i < g.length; i++)
g[i] = new Vector();
g[1].add(2);
g[2].add(1);
g[1].add(3);
g[3].add(1);
g[1].add(4);
g[4].add(1);
g[2].add(5);
g[5].add(2);
g[2].add(6);
g[6].add(2);
g[3].add(7);
g[7].add(3);
g[4].add(10);
g[10].add(4);
g[8].add(7);
g[7].add(8);
g[9].add(7);
g[7].add(9);
Vector v = new Vector<>();
v.add(7);
v.add(3);
v.add(8);
System.out.print(findLCA(n, g, v) +"\n");
}
}
// This code is contributed by aashish1995.
Python3
# Python Program to find the LCA
# in a rooted tree for a given
# set of nodes
from typing import List
from sys import maxsize
INT_MAX = maxsize
INT_MIN = -maxsize
# Set time 1 initially
T = 1
def dfs(node: int, parent: int, g: List[List[int]], level: List[int],
t_in: List[int], t_out: List[int]) -> None:
global T
# Case for root node
if (parent == -1):
level[node] = 1
else:
level[node] = level[parent] + 1
# In-time for node
t_in[node] = T
for i in g[node]:
if (i != parent):
T += 1
dfs(i, node, g, level, t_in, t_out)
T += 1
# Out-time for the node
t_out[node] = T
def findLCA(n: int, g: List[List[int]], v: List[int]) -> int:
# level[i]--> Level of node i
level = [0 for _ in range(n + 1)]
# t_in[i]--> In-time of node i
t_in = [0 for _ in range(n + 1)]
# t_out[i]--> Out-time of node i
t_out = [0 for _ in range(n + 1)]
# Fill the level, in-time
# and out-time of all nodes
dfs(1, -1, g, level, t_in, t_out)
mint = INT_MAX
maxt = INT_MIN
minv = -1
maxv = -1
for i in v:
# To find minimum in-time among
# all nodes in LCA set
if (t_in[i] < mint):
mint = t_in[i]
minv = i
# To find maximum in-time among
# all nodes in LCA set
if (t_out[i] > maxt):
maxt = t_out[i]
maxv = i
# Node with same minimum
# and maximum out time
# is LCA for the set
if (minv == maxv):
return minv
# Take the minimum level as level of LCA
lev = min(level[minv], level[maxv])
node = 0
l = INT_MIN
for i in range(n):
# If i-th node is at a higher level
# than that of the minimum among
# the nodes of the given set
if (level[i] > lev):
continue
# Compare in-time, out-time
# and level of i-th node
# to the respective extremes
# among all nodes of the given set
if (t_in[i] <= mint and t_out[i] >= maxt and level[i] > l):
node = i
l = level[i]
return node
# Driver code
if __name__ == "__main__":
n = 10
g = [[] for _ in range(n + 1)]
g[1].append(2)
g[2].append(1)
g[1].append(3)
g[3].append(1)
g[1].append(4)
g[4].append(1)
g[2].append(5)
g[5].append(2)
g[2].append(6)
g[6].append(2)
g[3].append(7)
g[7].append(3)
g[4].append(10)
g[10].append(4)
g[8].append(7)
g[7].append(8)
g[9].append(7)
g[7].append(9)
v = [7, 3, 8]
print(findLCA(n, g, v))
# This code is contributed by sanjeev2552
C#
// C# Program to find the LCA
// in a rooted tree for a given
// set of nodes
using System;
using System.Collections.Generic;
public class GFG
{
// Set time 1 initially
static int T = 1;
static void dfs(int node, int parent,
List []g,
int []level, int []t_in,
int []t_out)
{
// Case for root node
if (parent == -1)
{
level[node] = 1;
}
else
{
level[node] = level[parent] + 1;
}
// In-time for node
t_in[node] = T;
foreach (int i in g[node])
{
if (i != parent)
{
T++;
dfs(i, node, g,
level, t_in, t_out);
}
}
T++;
// Out-time for the node
t_out[node] = T;
}
static int findLCA(int n, List []g,
List v)
{
// level[i]-. Level of node i
int []level = new int[n + 1];
// t_in[i]-. In-time of node i
int []t_in = new int[n + 1];
// t_out[i]-. Out-time of node i
int []t_out = new int[n + 1];
// Fill the level, in-time
// and out-time of all nodes
dfs(1, -1, g,
level, t_in, t_out);
int mint = int.MaxValue, maxt = int.MinValue;
int minv = -1, maxv = -1;
for (int i = 0; i < v.Count; i++)
{
// To find minimum in-time among
// all nodes in LCA set
if (t_in[v[i]] < mint)
{
mint = t_in[v[i]];
minv = v[i];
}
// To find maximum in-time among
// all nodes in LCA set
if (t_out[v[i]] > maxt)
{
maxt = t_out[v[i]];
maxv = v[i];
}
}
// Node with same minimum
// and maximum out time
// is LCA for the set
if (minv == maxv)
{
return minv;
}
// Take the minimum level as level of LCA
int lev = Math.Min(level[minv], level[maxv]);
int node = 0, l = int.MinValue;
for (int i = 1; i <= n; i++)
{
// If i-th node is at a higher level
// than that of the minimum among
// the nodes of the given set
if (level[i] > lev)
continue;
// Compare in-time, out-time
// and level of i-th node
// to the respective extremes
// among all nodes of the given set
if (t_in[i] <= mint
&& t_out[i] >= maxt
&& level[i] > l)
{
node = i;
l = level[i];
}
}
return node;
}
// Driver code
public static void Main(String[] args)
{
int n = 10;
List []g = new List[n + 1];
for (int i = 0; i < g.Length; i++)
g[i] = new List();
g[1].Add(2);
g[2].Add(1);
g[1].Add(3);
g[3].Add(1);
g[1].Add(4);
g[4].Add(1);
g[2].Add(5);
g[5].Add(2);
g[2].Add(6);
g[6].Add(2);
g[3].Add(7);
g[7].Add(3);
g[4].Add(10);
g[10].Add(4);
g[8].Add(7);
g[7].Add(8);
g[9].Add(7);
g[7].Add(9);
List v = new List();
v.Add(7);
v.Add(3);
v.Add(8);
Console.Write(findLCA(n, g, v) +"\n");
}
}
// This code is contributed by Rajput-Ji
输出:
3
时间复杂度: O(N)
空间复杂度: O(N)
如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。