Écrivez le programme le plus court pour vérifier si un arbre binaire est équilibré

15

Pour chaque nœud dans un arbre binaire équilibré, la différence maximale dans les hauteurs du sous-arbre enfant gauche et du sous-arbre enfant droit est au plus 1.

La hauteur d'un arbre binaire est la distance entre le nœud racine et le nœud enfant le plus éloigné de la racine.

Voici un exemple:

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

Hauteur de l'arbre binaire: 4

Voici des arbres binaires et un rapport indiquant s'ils sont équilibrés ou non:

Cas de test 1

L'arbre ci-dessus est déséquilibré .

Cas de test 2

L'arbre ci-dessus est équilibré .

Écrivez le programme le plus court possible qui accepte en entrée la racine d'un arbre binaire et renvoie une valeur de falsey si l'arbre est déséquilibré et une valeur véridique si l'arbre est équilibré.

Contribution

La racine d'un arbre binaire. Cela peut être sous la forme d'une référence à l'objet racine ou même d'une liste qui est une représentation valide d'un arbre binaire.

Production

Renvoie une valeur véridique: si l'arbre est équilibré

Retourne la valeur de falsey: si l'arbre n'est pas équilibré.

Définition d'un arbre binaire

Un arbre est un objet qui contient une valeur et deux autres arbres ou pointeurs vers eux.

La structure de l'arbre binaire ressemble à ceci:

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

Si vous utilisez une représentation de liste pour un arbre binaire, elle peut ressembler à ceci:

[root_value, left_node, right_node]
T. Salim
la source
2
L'entrée peut-elle être un arbre vide?
tsh
1
Dans votre premier exemple d'arbre, si vous enlevez la feuille 4, l'arbre restant est-il équilibré?
Neil
Non, pas cet exemple, je voulais dire l'initiale, en utilisant l'art ASCII.
Neil
Selon ma propre implémentation "C, 117 octets": Non, puisque la hauteur de l'arbre de sous-bras droit à partir de "5" est 2 et la hauteur de l'arbre de sous-bras gauche est 0.
T. Salim
Les modifications sont d'au moins 6 caractères, mais veuillez supprimer la virgule entre `` équilibré '' et `` binaire '' - `` arbre binaire '' est un mot, donc écrire `` arbre binaire équilibré '' est l'équivalent de `` rouge, motoneige '' - le une virgule n'est pas requise.
Geza Kerecsenyi

Réponses:

8

Gelée , 11 octets

ḊµŒḊ€IỊ;߀Ạ

Essayez-le en ligne!

L'arbre vide est représenté par [].

Erik le Outgolfer
la source
Merci Erik d'avoir été parmi les premiers à répondre à cette question. La gelée est certainement une langue très populaire sur ce site. Je pense que je devrais prendre la liberté de mettre en œuvre ce langage. Bon à apprendre d'un langage de script de golf robuste.
T. Salim
Félicitations Erik l'Outgolfer, vous êtes gagnant.
T. Salim
3

Prolog (SWI) , 49 octets

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

Essayez-le en ligne!

Représente les arbres en tant que Value/Left_Child/Right_Child, l'arbre vide étant l'atome e. Définit +/2, qui génère un succès ou un échec, avec une variable indépendante (ou déjà égale à la hauteur de l'arborescence) à gauche et l'arborescence à droite - si l'argument hauteur est inacceptable, ajoutez 9 octets à définir -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.
Chaîne indépendante
la source
(Si la valeur de chaque nœud pouvait être omise de l'entrée, _/pourrait être supprimée pour -2 octets.)
Chaîne non
3

Wolfram Language (Mathematica) , 50 octets

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

Utilisez Nullpour null, value[left, right]pour les nœuds. Par exemple, l'arborescence suivante s'écrit 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

Essayez-le en ligne!

alephalpha
la source
C'est vraiment joli!
Greg Martin
3

Python 3.8 (pré-version) , 133 125 octets

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]

Essayez-le en ligne!

Prend un arbre au format "liste": Un nœud est [value, left, right]avec leftet rightétant des nœuds.

Appelez la fonction h.

Renvoie 0ou Falsepour un arbre déséquilibré. Renvoie 1ou Truepour un arbre équilibré.

Non 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: Logique inversée pour se débarrasser de nots

Si la prise d'arguments au milieu d'un appel est autorisée, cela pourrait être raccourci à (115 octets)

(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]

d' _être l'arbre à vérifier.

ar4093
la source
2

JavaScript, 162 octets

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}

Essayez-le en ligne!

Le format de l'entrée est un objet

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

Explication

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

En effectuant une première recherche en largeur, trouvez la profondeur du premier nœud auquel il manque une ou plusieurs branches.

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])}

En poursuivant la première recherche de largeur, retournez zéro si un élément est plus profond de deux que la profondeur des branches manquantes du premier nœud.

return 1}

Si aucun tel nœud n'est trouvé, retournez 1

fəˈnɛtɪk
la source
1
Il y a probablement un moyen de mieux faire la première recherche, mais je n'y ai pas pensé.
fəˈnɛtɪk
1
Je pense que cela échoue pour certains cas valides tels que le tout premier exemple qui devrait devenir équilibré lorsque vous retirez la feuille 4.
Neil
1

Julia, 56 octets

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

Avec la structure suivante représentant l'arbre binaire:

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

c est un tuple représentant les nœuds gauche et droit et le tuple vide () est utilisé pour signaler l'absence d'un nœud.

La valeur de Falsey est NaN, tout entier est vrai.

user3263164
la source
1
En supposant que le codage est UTF-8, il s'agit en fait de 57 octets à cause du , selon le compteur d'octets intégré de TIO . Quoi qu'il en soit, bienvenue chez CG&CC!
Unrelated String
1
Oui tu as raison. Je l'ai corrigé, pour qu'il soit désormais de 56 octets
user3263164
0

Kotlin , 67 octets

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

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

Essayez-le en ligne!

Brojowski
la source
0

C, 117 octets

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 mise en œuvre de Struct est la suivante:

 typedef struct T
    {
        struct T * l;

        struct T * r;

        int v;

    } T;

Essayez ceci sur JDoodle

T. Salim
la source
Cela semble être de 117 octets, mais vous pouvez le faire <2pour ce dernier contrôle à la place
Jo King
De plus, je ne sais pas à quel point cela est valide, car il repose sur une structure de données définie en dehors de la soumission
Jo King
0

Python 2 , 99 96 94 octets

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:]))

Essayez-le en ligne!

3 octets de Jo King .

Prend l'entrée comme: le nœud vide est [], et les autres nœuds le sont [<value>, <leftNode>, <rightNode>]. Sorties 0/1pour False / True.

Chas Brown
la source