Напишіть найкоротшу програму, щоб перевірити, чи врівноважене двійкове дерево


15

Для кожного вузла в збалансованому двійковому дереві максимальна різниця у висоті лівого дочірнього дерева та правого дочірнього піддерев’я становить не більше 1.

Висота двійкового дерева - це відстань від кореневого вузла до дочірнього вузла, що знаходиться найдалі від кореня.

Нижче наведено приклад:

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

Висота двійкового дерева: 4

Далі наведені двійкові дерева та звіт про збалансованість чи ні:

Тестовий випадок 1

Дерево вгорі незбалансоване .

Тестовий випадок 2

Наведене вище дерево збалансовано .

Напишіть найкоротшу можливу програму, яка приймає як вхід корінь двійкового дерева і повертає значення фальси, якщо дерево не врівноважене, а триєчне значення, якщо дерево збалансоване.

Вхідні дані

Корінь двійкового дерева. Це може бути у вигляді посилання на кореневий об'єкт або навіть список, що є дійсним поданням бінарного дерева.

Вихідні дані

Повертає трибунове значення: Якщо дерево збалансовано

Повертає значення фальси: Якщо дерево не врівноважено.

Визначення бінарного дерева

Дерево - це об'єкт, який містить значення і два інші дерева, або покажчики на них.

Структура двійкового дерева виглядає приблизно так:

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

Якщо використовується представлення списку для двійкового дерева, воно може виглядати приблизно так:

[root_value, left_node, right_node]

2
Може вхід буде порожнім деревом?
TSH

1
У вашому первинному прикладі дерева, якщо ви видалите листочок 4, чи залишилося дерево збалансованим?
Ніл

Ні, не той приклад, я мав на увазі початковий, використовуючи ASCII art.
Ніл

Згідно з моєю власною реалізацією "C, 117 байт": Ні, оскільки висота правого підводного дерева, починаючи з "5", дорівнює 2, а висота лівого дерева підводного зброї - 0.
Салім

Зміни становлять щонайменше 6 знаків, але, будь ласка, видаліть кому між 'врівноваженим' та 'двійковим' - 'бінарне дерево' є іменниковою фразою, тому написання "врівноважене, бінарне дерево" є еквівалентом "червоний, сніговий мобільний" - кома не потрібна.
Geza Kerecsenyi

Відповіді:


8

Желе , 11 байт

ḊµŒḊ€IỊ;߀Ạ

Спробуйте в Інтернеті!

Порожнє дерево представлено символом [].


Дякую Еріку за те, що був одним із перших, хто відповів на це питання. Желе, безумовно, є дуже популярною мовою на цьому сайті. Думаю, я мав би сміливо реалізувати цю мову. Добре вивчити надійну мову гольф-сценаріїв.
Т. Салим

Поздравляю Еріка Переможця, ви переможець.
Т. Салим

3

Пролог (SWI) , 49 байт

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

Спробуйте в Інтернеті!

Представляє дерева як Value/Left_Child/Right_Child, при цьому порожнє дерево є атомом e. Визначає +/2, що виводить через успіх чи невдачу, з незв'язаною змінною (або такою, яка вже дорівнює висоті дерева) зліва та деревом праворуч - якщо аргумент висоти неприйнятний, додайте 9 байт для визначення -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.

(Якщо значення кожного вузла можна було пропустити з введення, його _/можна
Непов'язаний рядок

3

Мова Вольфрама (Mathematica) , 50 байт

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

Використовувати Nullдля null, value[left, right]для вузлів. Наприклад, таке дерево записується як 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

Спробуйте в Інтернеті!


Це справді красиво!
Грег Мартін

3

Python 3.8 (попередній випуск) , 133 125 байт

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]

Спробуйте в Інтернеті!

Бере дерево у форматі "список": Вузол є [value, left, right] з leftіright є вузли.

Викликати функцію h .

Повертається 0або Falseдля незбалансованого дерева. Повертається1 абоTrue для збалансованого дерева.

Безголівки:

# 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: зворотна логіка позбутися not s

Якщо дозволяється брати аргументи посеред дзвінка, це може бути скорочено до (115 байт)

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

з _тим, щоб бути деревом для перевірки.



2

JavaScript, 162 байти

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}

Спробуйте в Інтернеті!

Формат вводу - об’єкт

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

Пояснення

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}

Якщо такого вузла не знайдено, поверніть 1


1
Мабуть, є якийсь спосіб зробити перший широкий пошук краще, але я не міг про це думати.
fəˈnɛtɪk

1
Я думаю, що це не вдається для деяких дійсних випадків, таких як перший приклад, який повинен стати врівноваженим, коли ви виймаєте лист 4.
Ніл

1

Юлія, 56 байт

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

З такою структурою, що представляє двійкове дерево:

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

cявляє собою кортеж, що представляє лівий і правий вузли, і порожній кортеж ()використовується для сигналізації про відсутність вузла.

Значення Фальсі є NaN, будь-яке ціле число є правдою.


1
Якщо припустити , що кодування є UTF-8, це насправді 57 байт , з - за , в відповідно до вбудованим в байт лічильника TiO в . У будь-якому випадку, ласкаво просимо до CG&CC!
Непов’язана струна

1
Так, ви праві. Я виправив це так, що тепер він фактично 56 байт
user3263164


0

C, 117 байт

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;}

Реалізація структури полягає в наступному:

 typedef struct T
    {
        struct T * l;

        struct T * r;

        int v;

    } T;

Спробуйте це на JDoodle


Здається, це 117 байт, хоча <2замість цього можна зробити останній перевірки
Джо Кінг

Крім того, я не впевнений, наскільки це справедливо, оскільки він спирається на структуру даних, визначену поза поданням
Jo King

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.