Dado un árbol enraizado con N Nodes, la tarea es encontrar el antepasado común más bajo para un conjunto dado de Nodes V de ese árbol.
Ejemplos:
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
Enfoque: Podemos observar que
- los ancestros comunes más bajos para cualquier conjunto de Nodes tendrán un tiempo de entrada menor o igual que el de todos los Nodes del conjunto y un tiempo de salida mayor o igual (igual si LCA está presente en el conjunto) al de todos los Nodes en el conjunto.
- Por lo tanto, para resolver el problema, necesitamos recorrer todo el árbol comenzando desde el Node raíz utilizando el recorrido de búsqueda primero en profundidad y almacenar el tiempo de entrada, el tiempo de salida y el nivel para cada Node.
- El Node con un tiempo de entrada menor o igual que todos los Nodes del conjunto y un tiempo de salida mayor o igual que todos los Nodes del conjunto y con el máximo nivel posible es la respuesta.
A continuación se muestra la implementación del enfoque anterior:
C++
// C++ Program to find the LCA // in a rooted tree for a given // set of nodes #include <bits/stdc++.h> using namespace std; // Set time 1 initially int T = 1; void dfs(int node, int parent, vector<int> 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<int> g[], vector<int> 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<int> 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<int> 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<Integer> 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<Integer> g[], Vector<Integer> 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 <v.size(); i++) { // To find minimum in-time among // all nodes in LCA set if (t_in[v.get(i)] < mint) { mint = t_in[v.get(i)]; minv = v.get(i); } // To find maximum in-time among // all nodes in LCA set if (t_out[v.get(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<Integer> []g = new Vector[n + 1]; for (int i = 0; i < g.length; i++) g[i] = new Vector<Integer>(); 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<Integer> 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<int> []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<int> []g, List<int> 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<int> []g = new List<int>[n + 1]; for (int i = 0; i < g.Length; i++) g[i] = new List<int>(); 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<int> v = new List<int>(); v.Add(7); v.Add(3); v.Add(8); Console.Write(findLCA(n, g, v) +"\n"); } } // This code is contributed by Rajput-Ji
Javascript
<script> // JavaScript Program to find the LCA // in a rooted tree for a given // set of nodes // Set time 1 initially let T = 1; function dfs(node, parent, g, level, t_in, 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 (let i = 0; i < g[node].length; i++) { if (g[node][i] != parent) { T++; dfs(g[node][i], node, g, level, t_in, t_out); } } T++; // Out-time for the node t_out[node] = T; } function findLCA(n, g, v) { // level[i]-. Level of node i let level = new Array(n + 1); // t_in[i]-. In-time of node i let t_in = new Array(n + 1); // t_out[i]-. Out-time of node i let t_out = new Array(n + 1); // Fill the level, in-time // and out-time of all nodes dfs(1, -1, g, level, t_in, t_out); let mint = Number.MAX_VALUE, maxt = Number.MIN_VALUE; let minv = -1, maxv = -1; for (let i =0; i < v.length; 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 let lev = Math.min(level[minv], level[maxv]); let node = 0, l = Number.MIN_VALUE; for (let 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; } let n = 10; let g = new Array(n + 1); for (let i = 0; i < g.length; i++) g[i] = []; g[1].push(2); g[2].push(1); g[1].push(3); g[3].push(1); g[1].push(4); g[4].push(1); g[2].push(5); g[5].push(2); g[2].push(6); g[6].push(2); g[3].push(7); g[7].push(3); g[4].push(10); g[10].push(4); g[8].push(7); g[7].push(8); g[9].push(7); g[7].push(9); let v = []; v.push(7); v.push(3); v.push(8); document.write(findLCA(n, g, v) +"</br>"); </script>
Producción:
3
Complejidad temporal: O(N)
Complejidad espacial: O(N)
Publicación traducida automáticamente
Artículo escrito por akarshan2000 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA