2 arbori binari sunt egale sau nu

voturi
7

Posibil dublură:
Determinați dacă doi arbori binari sunt egale

Ai un interviu ieri, o întrebare mi-a ajuns, aici este:

Descriere

Există 2 binary trees, verificați dacă acestea sunt egale.

Ele sunt egale dacă și numai dacă tree1->child == tree2->child, și un copac la stânga și la dreapta children can be swapped with each other.

De exemplu:

    5     6
   / \   / \           they are equal.
   1 2   2  1

    5         6
   / \       / \           they are equal.
  1   2     2   1
 /     \   /    / 
3       4 4     3

Orice idei sunt apreciate.

Întrebat 12/10/2011 la 01:18
sursa de către utilizator
În alte limbi...                            


6 răspunsuri

voturi
9

Operatorii sunt tranzitive de egalitate: Dacă A = B și B = C, atunci A = B = C deci A = C.

Operatorii de egalitate sunt reflexive: A = A, B = B, și C = C, indiferent de valorile lor sunt.

Operatorii de egalitate sunt simetrice. Dacă A = B, atunci B = A. (Nu contează ce ordine acestea sunt.)

Acum, luând o privire la definiția ți-au dat:

Un copac este egal cu un alt copac în cazul în care copiii sunt egali. Sa vedem. Putem presupune că nodurile sunt comparate în partea de jos, sau altfel definiția este destul de inutil. Dar ei nu deranjează să-ți spun cum să rezolve această comparație, și întreaga definiție ți-au dat depinde de ea.

Pe scurt, este o chestiune de doi bani.

Să vedem ce se întâmplă dacă decidem vrem să încercăm să dezlege problema, totuși.

Dar stai, ei vă spun , de asemenea , că cei doi copii de orice copac pot fi schimbate. Aceasta adaugă constrângerea că orice pom , care este egal cu orice altceva (inclusiv în sine) trebuie să fie egală cu imaginea sa în oglindă. Și orice variații ale copiilor subarbori săi fiind schimbate.

Și amintiți - vă că acest lucru ar trebui să fie o căutare copac. Prin urmare, putem presupune , probabil , că doi arbori de căutare diferite care sunt procesate de același algoritm trebuie să dea același rezultat , dacă acestea sunt egale. Deci, dacă vom trece în jurul valorii de elementele unui copac, atunci timpul de căutare va fi afectată. Deci, copacii care nu au fiecare nod în loc nu sunt egale între ele.

Punerea că, împreună cu proprietatea „swappable“ a acestei egalitati, putem vedea că nu este o definiție validă a egalității. (Dacă vom încerca să-l aplice, atunci se dovedește că numai copacii care au același nod pentru fiecare nod la un anumit nivel sunt egale, și numai pentru ei înșiși, care rupe partea reflexivitate a unui operator de egalitate.)

Publicat 12/10/2011 la 01:24
sursa de către utilizator

voturi
3

Dacă implementați definiția lor de „egalitate“ cu flip-invarianta, vă va încălca definiția egalității. Definiția nu are nici un sens, pentru că nu este modul în care copacii de căutare binare sunt egale (cu excepția cazului în fiecare nod are un pointer la care subarborele este „mai mare“ și care este „mai mic“).

Ai două variante de definiții rezonabile:

  1. topologic (flip-agnostic) echivalență (caz în care nu se poate numi un „arbore binar de căutare“ , deoarece nu este sortate):

    tree1==tree2 mijloace set(tree1.children)==set(tree2.children)

  2. căutare arbore normal (flip-îngrijire) echivalență:

    tree1==tree2 mijloace list(tree1.children)==list(tree2.children)

Pentru arbori binari, definițiile de mai sus vor lucra ca scrise în orice limbă , care sprijină listși settipuri de date (seturi de piton va sufoca însă pe tipuri de date unhashable). Cu toate acestea, mai jos sunt câteva definiții C / Java , cum ar fi mai logoreic și urât:

  1. echivalență topologic:

    t1==t2 mijloace (t1.left==t2.left and t1.right==t2.right) or (t1.left==t2.right and t1.right==t2.left)

  2. sortat echivalență copac:

    t1==t2 mijloace (t1.left==t2.left and t1.right==t2.right)

Definițiile de mai sus sunt recursive; adică, ei presupun egalitate a fost definit pentru subramificații și de baze de cazuri deja, pe care le are.


notă marginală:

Citat: tree1-> copil == tree2-> copil

Aceasta nu este o afirmație valabilă, pentru că un nod copac nu are un singur copil.

Publicat 12/10/2011 la 02:20
sursa de către utilizator

voturi
7

Nu cred că aceasta este o întrebare rezonabilă. O soluție simplă recursiva este

boolean equals(x, y)
{
  if (x == null)
  {
    return y == null;
  }
  if (y == null)
  {
    return false;
  }
  if (x.val != y.val)
  {
    return false;
  }
  if (equals(x.left, y.left) && equals(x.right, y.right))
  {
    return true;
  }
  if (equals(x.left, y.right) && equals(x.right, y.left))
  {
    return true;
  }
  return false;
}

Acest lucru poate fi foarte costisitoare, de exemplu, în cazul în care avem doi copaci mari de formă similară în cazul în care toate nodurile non-frunze au aceeași valoare asociată și nodurile frunze ale unuia sunt o permutare a nodurilor frunze de o alta.

Pentru a obține acest lucru ar putea fi salvat în primul rând o schimbare la stânga și la dreapta după cum este necesar, astfel încât stânga <dreapta, pentru o definiție recursivă a <. Acest lucru ar putea fi, de asemenea, scump, dar mult mai puțin decât verificarea fiecare permutare, și cred că o alegere de definiție a <ar ajuta. Acest lucru ar permite apoi să verificați pentru egalitatea cu o definiție obișnuită.

Această noțiune de http://en.wikipedia.org/wiki/Canonicalization urmată de egalitate ordinară rezolvă , de asemenea , întrebări cu privire dacă într-adevăr aveți o relație de echivalență. O relație de echivalență este echivalentă cu o partiție. Egalitate ordinară este , evident , o partiție. Dacă compara x și y prin compararea f (x) și f (y) , urmată de o relație de echivalență aveți o partiție de x și y, și , prin urmare , o relație de echivalență.

Gândire mai multe despre acest lucru, cred că modul de a face fie canonicalisation sau egalitatea de testare în mod rezonabil eficiente este de a lucra de jos în sus, adnotarea fiecare nod cu un simbol a cărui valoare reflectă rezultatul comparații cu alte noduri, astfel încât să puteți compara noduri , iar subramificații sub ele, fie doar compararea token-uri.

Deci, primul pas pentru egalitate este de a utiliza de exemplu un tabel hash pentru a adnota fiecare frunză cu jetoanele care sunt egale numai atunci când valorile la frunzele sunt egale. Apoi, pentru noduri ale căror copii sunt numai frunze, de exemplu, utilizați un tabel hash pentru a atribui token-uri suplimentare, astfel încât semnele în aceste noduri sunt egale numai atunci când frunzele, dacă este cazul, sub aceste noduri meci. Apoi, puteți merge un pas mai mult în sus, și de data aceasta, puteți compara token-uri la nodurile copil în loc de recursiune copacul acolo. Costul de a atribui token-uri în acest fel ar trebui să fie liniar în dimensiunea arborilor implicate. In partea de sus poti compara copaci doar prin compararea jetoanele de la rădăcină.

Publicat 12/10/2011 la 06:57
sursa de către utilizator

voturi
0

Am citit întrebările ca: dat doi arbori binari, pentru fiecare adâncime în copac, pentru a afla dacă setul de copii lor sunt acoperite unul în celălalt.

Acest lucru poate fi codificate relativ ușor.

Publicat 12/10/2011 la 12:30
sursa de către utilizator

voturi
0

Soluție fără recursivitate în Ruby

def same? top_t1, top_t2
  for_chek << [top_t1, top_t2]   # (1) put task for check into queue

  while t1,t2 = for_check.shift  # (2)
    return false unless t1.children.count == t2.children.count  # generally for non-binary tree, but also needed for controlling of nil children
    break if t1.children.empty?

    t1_children = t1.children.sort # this is sorted arrays
    t2_children = t2.children.sort # of childrens      
    return false unless t1_children == t2_children  # (3)

    0.upto(t1_children.count - 1) do |i|
      for_check << [t1_children[i], t2_children[i]]  # put equivalent child pairs into queue
    end
  end
  return true
end

Ruby sfaturi de sintaxă:

  • (1) punerea elementului în matrice: arr << elem; în acest caz for_checkeste matrice de matrice
  • (2) Atribuirea paralelă: t1,t2 = [item1, item2]. La fel caarr = [item1, item2]; t1 = arr[0]; t2 = arr[1]
  • (3) t1_children == t2_childrenpresupus comportament corespunzător de == pentru acest tip de obiecte. Mai multe verbose va fi t1_children.map { |el| el.val } == t2_children.map { |el| el.val }- aici mapproduce matrice de Vals.
Publicat 15/10/2011 la 16:17
sursa de către utilizator

voturi
1

Compara copaci folosind abordarea sugerată de canonizare @mcdowella . Diferența este că abordarea mea nu are nevoie de O(N)memorie suplimentară numărul WRT de noduri din arbore:

# in Python
from collections import namedtuple
from itertools import chain

# Tree is either None or a tuple of its value and left, right trees
Tree = namedtuple('Tree', 'value left right')

def canonorder(a, b):
    """Sort nodes a, b by their values.

    `None` goes to the left
    """
    if (a and b and a.value > b.value) or b is None:
        a, b = b, a # swap
    return a, b

def canonwalk(tree, canonorder=canonorder):
    """Yield all tree nodes in a canonical order.

    Bottom-up, smaller children first, None is the smallest
    """
    if tree is not None:
        children = tree[1:]
        if all(t is None for t in children): return # cut None leaves
        children = canonorder(*children)            
        for child in chain(*map(canonwalk, children)):
            yield child
    yield tree 

canonwalk()necesită O(N*M)pași și O(log(N)*M)memorie pentru a produce toate nodurile dintr - un copac, unde Neste numărul total de noduri, Mnumărul de copii fiecare nod are (este 2 pentru arbori binari).

canonorder()ar putea fi ușor generalizată pentru orice reprezentare nod și orice număr de copii. canonwalk()necesită doar ca un copac poate avea acces la copiii săi imediați ca secvență.

Funcția de comparație solicită canonwalk():

from itertools import imap, izip_longest

unset = object() 
def cmptree(*trees):
    unequal = False # allow root nodes to be unequal
    # traverse in parallel all trees under comparison
    for nodes in izip_longest(*imap(canonwalk, trees), fillvalue=unset):
        if unequal:
            return False # children nodes are not equal
        if any(t is unset for t in nodes):
            return False # different number of nodes
        if all(t is not None for t in nodes):
            unequal = any(nodes[-1].value != t.value for t in nodes)
        else: # some are None
            unequal = any(t is not None for t in nodes)
    return True # equal

Exemplu

    5         6
   / \       / \           they are equal.
  1   2     2   1
 /     \   /    / 
3       4 4     3

tree1 = Tree(5, 
             Tree(1, 
                  Tree(3, None,None), None), 
             Tree(2, 
                  None, Tree(4, None, None)))
tree2 = Tree(6, 
             Tree(2, Tree(4, None, None), None),
             Tree(1, Tree(3, None, None), None))
print cmptree(tree1, tree2)

producție

True
Publicat 15/10/2011 la 21:10
sursa de către utilizator

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more