Escriba el programa más corto para verificar si un árbol binario está equilibrado

15

Para cada nodo en un árbol binario equilibrado, la diferencia máxima en las alturas del subárbol secundario izquierdo y el subárbol secundario derecho es como máximo 1.

La altura de un árbol binario es la distancia desde el nodo raíz al nodo hijo que está más alejado de la raíz.

A continuación se muestra un ejemplo:

           2 <-- root: Height 1
          / \
         7   5 <-- Height 2
        / \   \
       2   6   9 <-- Height 3
          / \  /
         5  11 4 <-- Height 4 

Altura del árbol binario: 4

Los siguientes son árboles binarios y un informe sobre si están equilibrados o no:

Caso de prueba 1

El árbol de arriba está desequilibrado .

Caso de prueba 2

El árbol de arriba es equilibrado. .

Escriba el programa más corto posible que acepte como entrada la raíz de un árbol binario y devuelva un valor falsey si el árbol está desequilibrado y un valor verdadero si el árbol está equilibrado.

Entrada

La raíz de un árbol binario. Esto puede ser en forma de una referencia al objeto raíz o incluso una lista que es una representación válida de un árbol binario.

Salida

Devuelve el valor verdadero: si el árbol está equilibrado

Devuelve el valor de falsey: si el árbol es un equilibrado.

Definición de un árbol binario

Un árbol es un objeto que contiene un valor y otros dos árboles o punteros a ellos.

La estructura del árbol binario se parece a la siguiente:

typedef struct T
{
   struct T *l;
   struct T *r;
   int v;
}T;

Si usa una representación de lista para un árbol binario, puede tener un aspecto similar al siguiente:

[root_value, left_node, right_node]
T. Salim
fuente
2
¿La entrada puede ser un árbol vacío?
tsh
1
En su ejemplo inicial de un árbol, si quita la hoja 4, ¿está equilibrado el árbol restante?
Neil
No, no ese ejemplo, quise decir el inicial, usando el arte ASCII.
Neil
De acuerdo con mi propia implementación "C, 117 bytes": No, ya que la altura del árbol de subarmas derecho a partir de "5" es 2 y la altura del árbol de subarmas izquierdo es 0.
T. Salim
Las ediciones son al menos 6 caracteres, pero elimine la coma entre 'equilibrado' y 'binario' - 'árbol binario' es una frase nominal, por lo que escribir 'árbol binario equilibrado' es el equivalente de 'rojo, móvil de nieve' - el no se requiere coma
Geza Kerecsenyi

Respuestas:

8

Jalea , 11 bytes

ḊµŒḊ€IỊ;߀Ạ

Pruébalo en línea!

El árbol vacío está representado por [].

Erik el Outgolfer
fuente
Gracias Erik por estar entre los primeros en responder esta pregunta. Jelly ciertamente es un lenguaje muy popular en este sitio. Creo que debería tomarme la libertad de implementar este lenguaje. Es bueno aprender de un lenguaje robusto de scripting de golf.
T. Salim
Felicidades Erik the Outgolfer, eres el ganador.
T. Salim
3

Prólogo (SWI) , 49 bytes

N+_/B/C:-X+B,Y+C,abs(X-Y)<2,N is max(X,Y)+1.
0+e.

Pruébalo en línea!

Representa los árboles como Value/Left_Child/Right_Child, siendo el árbol vacío el átomo e. Define +/2, que sale por éxito o fracaso, con una variable independiente (o una ya igual a la altura del árbol) a la izquierda y el árbol a la derecha; si el argumento de altura es inaceptable, agregue 9 bytes para definir-T:-_+T. .

N + _/B/C :-            % If the second argument is a tree of the form _Value/B/C,
    X+B,                % X is the height of its left child which is balanced,
    Y+C,                % Y is the height of its right child which is balanced,
    abs(X-Y) < 2,       % the absolute difference between X and Y is strictly less than 2,
    N is max(X,Y)+1.    % and N is the height of the full tree.
0 + e.                  % If, on the other hand, the second argument is e, the first is 0.
Cadena no relacionada
fuente
(Si el valor de cada nodo pudiera omitirse de la entrada, _/podría extraerse por -2 bytes.)
Cadena no relacionada
3

Wolfram Language (Mathematica) , 50 bytes

f@_[x_,y_]:=f@x&&f@y&&-2<Depth@x-Depth@y<2;f@_=1>0

Usar Nullpara nulo, value[left, right]para nodos. Por ejemplo, el siguiente árbol se escribe como 2[7[2[Null, Null], 6[5[Null, Null], 11[Null, Null]]], 5[Null, 9[4[Null, Null], Null]]].

    2
   / \
  7   5
 / \   \
2   6   9
   / \  /
  5  11 4

Pruébalo en línea!

alephalpha
fuente
Eso es realmente bonito!
Greg Martin el
3

Python 3.8 (prelanzamiento) , 133125 bytes

b=lambda t:((max(l[0],r[0])+1,abs(l[0]-r[0])<2)if(l:=b(t[1]))[1]and(r:=b(t[2]))[1]else(0,0))if t else(0,1)
h=lambda t:b(t)[1]

Pruébalo en línea!

Toma un árbol en el formato de "lista": un nodo está [value, left, right]con leftyright siendo nodos.

Invocar la función h .

Devoluciones 0o Falsepara un árbol desequilibrado. Devoluciones 1oTrue para un árbol equilibrado.

Sin golf:

# Returns tuple (current height, subtrees are balanced (or not))
def balanced(tree):
  if tree: # [] evaluates to False
    left = balanced(tree[1])
    right = balanced(tree[2])
    # If  the subtrees are not both balanced, nothing to do, just pass it up
    if left[1] and right[1]:
      height = max(left[0], right[0]) + 1
      subtrees_balanced = abs(left[0] - right[0]) < 2
    else:
      height = 0 # Value doesn't matter, will be ignored
      subtrees_balanced = False
  else:
    height = 0
    subtrees_balanced = True
  return (height, subtrees_balanced)

def h(tree):
  return balanced(tree)[1]

-10: lógica invertida para deshacerse de not s

Si se permite tomar argumentos en medio de una llamada, esto podría acortarse a (115 bytes)

(b:=lambda t:((max(l[0],r[0])+1,abs(l[0]-r[0])<2)if(l:=b(t[1]))[1]and(r:=b(t[2]))[1]else(0,0))if t else(0,1))(_)[1]

con _ser el árbol para verificar.

ar4093
fuente
2

JavaScript, 162 bytes

f=x=>{for(f=0,s=[[x,1]];s[0];){if(!((d=(t=s.pop())[0]).a&&d.b||f))f=t[1];if(f&&t[1]-f>1)return 0;if(d.a)s.push([d.a,t[1]+1]);if(d.b)s.push([d.b,t[1]+1])}return 1}

Pruébalo en línea!

El formato de la entrada es un objeto.

root={a:{node},b:{node},c:value}

Explicación

for(f=0,s=[[x,1]];s[0];){if(!((d=(t=s.pop())[0]).a&&d.b||f))f=t[1]

Al realizar la primera búsqueda de amplitud, encuentre la profundidad del primer nodo al que le faltan una o más ramas.

if(f&&t[1]-f>1)return 0;if(d.a)s.push([d.a,t[1]+1]);if(d.b)s.push([d.b,t[1]+1])}

Continuando con la primera búsqueda de ancho, devuelve cero si algún elemento es dos más profundo que la profundidad de las ramas que faltan en el primer nodo.

return 1}

Si no se encuentra dicho nodo, devuelva 1

fəˈnɛtɪk
fuente
1
Probablemente haya alguna manera de hacer mejor la búsqueda de amplitud, pero no se me ocurrió.
fəˈnɛtɪk
1
Creo que esto falla en algunos casos válidos, como el primer ejemplo que debe equilibrarse al quitar la hoja 4.
Neil
1

Julia, 56 bytes

f(t)=t!=()&&(-(f.(t.c)...)^2<2 ? maximum(f,t.c)+1 : NaN)

Con la siguiente estructura que representa el árbol binario:

struct Tree
    c::NTuple{2,Union{Tree,Tuple{}}}
    v::Int
end

ces una tupla que representa los nodos izquierdo y derecho y la tupla vacía ()se usa para indicar la ausencia de un nodo.

El valor de Falsey es que NaNcualquier número entero es verdadero.

usuario3263164
fuente
1
Suponiendo que la codificación es UTF-8, esto es en realidad 57 bytes debido a , según el contador de bytes incorporado de TIO . De todos modos, ¡bienvenido a CG&CC!
Cadena no relacionada
1
Sí tienes razón. Lo corregí, de modo que ahora son en realidad 56 bytes
user3263164
0

Kotlin , 67 bytes

fun N.c():Int=maxOf(l?.c()?:0,r?.c()?:0)+1
fun N.b()=l?.c()==r?.c()

Dónde

data class N(val l: N? = null, val r: N? = null, val v: Int = 0)

Pruébalo en línea!

Brojowski
fuente
0

C, 117 bytes

h(T*r){r=r?1+h(h(r->l)>h(r->r)?r->l:r->r):0;}b(T*r){return r->l&&!b(r->l)||r->r&&!b(r->r)?0:abs(h(r->l)-h(r->r))<=1;}

La implementación de la estructura es la siguiente:

 typedef struct T
    {
        struct T * l;

        struct T * r;

        int v;

    } T;

Prueba esto en JDoodle

T. Salim
fuente
Esto parece ser de 117 bytes, aunque puede hacerlo <2para esa última verificación en su lugar
Jo King
Además, no estoy seguro de cuán válido es esto, ya que se basa en una estructura de datos definida fuera del envío
Jo King,
0

Python 2 , 99 96 94 bytes

lambda A:A==[]or(abs(D(A[1])-D(A[2]))<2)*f(A[1])*f(A[2])
D=lambda A:A>[]and-~max(map(D,A[1:]))

Pruébalo en línea!

3 bytes de Jo King .

Toma la entrada como: el nodo vacío es [], y otros nodos son [<value>, <leftNode>, <rightNode>]. Salidas 0/1para falso / verdadero.

Chas Brown
fuente