Mi respuesta es O(n^2)
, pero creo que es precisa, y toma un ligeramente enfoque diferente y parece más fácil de implementar.
Suponga que el valor almacenado en el nodo i
se denota por VALUE[i]
. Mi idea es almacenar en cada nodo la suma de los valores en la ruta desde root
a ese nodo. Por lo tanto, para cada nodo i
, SUM[i]
es la suma de la ruta de root
al nodo i
.
Luego, para cada par de nodos (i,j)
, busque su ancestro común k
. Si SUM(i)+SUM(j)-SUM(k) = TARGET_SUM
, ha encontrado una respuesta.
Esto es O(n^2)
ya que estamos haciendo un bucle sobre todos los pares de nodos. Aunque, desearía poder encontrar una mejor manera que simplemente escoger todas las parejas.
Podríamos optimizarlo un poco descartando subárboles donde el value
del nodo enraizado en el subárbol es mayor que TARGET_SUM
. Optimizaciones adicionales son bienvenidos :)
psuedocode:
# Skipping code for storing sum of values from root to each node i in SUM[i]
for i in nodes:
for j in nodes:
k = common_ancestor(i,j)
if (SUM[i] + SUM[j] - SUM[k] == TARGET_SUM):
print_path(i,k,j)
Función common_ancestor
es un problema bastante estándar para un árbol de búsqueda binaria. Psuedocode (de memoria, afortunadamente no hay errores!):
sub common_ancestor (i, j):
parent_i = parent(i)
# Go up the parent chain until parent's value is out of the range.
# That's a red flag.
while(VAL[i] <= VAL[parent_i] <= VAL[j]) :
last_parent = parent_i
parent_i = parent(i)
if (parent_i == NULL): # root node
break
return last_parent
@ la raíz es 2, el subárbol izquierdo es 1, y el subárbol derecho es 3 en el ejemplo publicado – TimeToCodeTheRoad
Prefiero usar un gráfico bidireccional (con conexiones de nodos limitadas) para ese propósito. Bin árboles (al menos para mí) implican una única dirección fija. – fjdumont
¿Cómo ayuda esto? – marcog