2 binaire bomen gelijk of niet

stemmen
7

Mogelijke dupliceren:
Bepaal of twee binaire bomen zijn gelijk

Kreeg een interview gisteren, een vraag kreeg me, hier is het:

Omschrijving

Er zijn 2 binary trees, controleer dan of ze gelijk zijn.

Ze zijn gelijk als en slechts als tree1->child == tree2->child, en één boom naar links en rechts children can be swapped with each other.

Bijvoorbeeld:

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

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

Alle ideeën worden gewaardeerd.

De vraag is gesteld op 12/10/2011 om 01:18
bron van user
In andere talen...                            


6 antwoorden

stemmen
9

Gelijkheid operators transitieve: Als A = B en B = C, dan A = B = C zodat A = C.

Gelijkheid operators zijn reflexieve: A = A, B = B, en C = C, ongeacht wat hun waarden zijn.

Gelijkheid operators zijn symmetrisch. Indien A = B en B = A. (Het maakt niet uit welke volgorde ze zich bevinden.)

Nu, met een blik op de definitie gaven ze je:

Een boom is gelijk aan een andere boom als de kinderen gelijk zijn. Laten we eens kijken. We kunnen aannemen dat de knooppunten worden vergeleken aan de onderkant, of anders de definitie is vrij nutteloos. Maar ze niet de moeite om je te vertellen hoe je die vergelijking op te lossen, en de hele definitie gaven ze je hangt af van het.

Kortom, het is een waardeloze vraag.

Laten we eens kijken wat er gebeurt als we besluiten dat we willen proberen en het ontrafelen van de vraag, dat wel.

Maar wacht, ze je ook vertellen dat de twee kinderen van elke boom kan worden verwisseld. Dit voegt de beperking dat elke boom die gelijk is aan iets anders (inclusief zichzelf) gelijk zijn spiegelbeeld te moeten zijn. En alle variaties van de kinderen haar substructuren worden verwisseld.

En vergeet niet dat dit wordt verondersteld te zijn een zoekactie boom. Daarom kunnen we waarschijnlijk aannemen dat twee verschillende search bomen die worden verwerkt door dezelfde algoritme moet hetzelfde resultaat geven als ze gelijk zijn. Dus, als we overschakelen rond de elementen van een boom, dan is de zoektijd zou worden beïnvloed. Dus, bomen die niet elk knooppunt hebben op zijn plaats zijn niet aan elkaar gelijk.

Putting die samen met de "swap" eigenschap van deze gelijkheid, kunnen we zien dat het geen geldige definitie van gelijkheid. (Als we proberen om het toe te passen, dan blijkt dat alleen bomen die hetzelfde knooppunt voor elk knooppunt hebben op een bepaald niveau gelijk zijn, en alleen voor zichzelf, waardoor de reflexiviteit onderdeel van een operator gelijkheid breekt.)

antwoordde op 12/10/2011 om 01:24
bron van user

stemmen
3

Als je hun definitie van "gelijkheid" met flip-invariantie te voeren, vindt u de definitie van gelijkheid te schenden. De definitie niet eens zin te maken, want dat is niet hoe binary search bomen gelijk zijn (tenzij elk knooppunt heeft een pointer naar die deelboom "groter" en dat is "mindere").

Je hebt twee keuzes van redelijke definities:

  1. topologische (flip-agnostisch) gelijkwaardigheid (in dat geval kun je het niet noemen het een "binary search tree" omdat het niet gesorteerd):

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

  2. normaal zoekboom (flip-verzorgende) gelijkwaardigheid:

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

Binaire bomen, zal bovenstaande definities werken als geschreven in een taal die het ondersteunt listen setdatatypes (python sets echter stikken unhashable datatypes). Niettemin, hieronder zijn wat meer uitgebreide en lelijk C / Java-achtige definities:

  1. topologische equivalentie:

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

  2. gesorteerde boom gelijkwaardigheid:

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

De bovenstaande definities recursief; dat wil zeggen, zij veronderstellen gelijkheid gedefinieerd voor de deelbomen en basis-gevallen al, waarin zij.


kanttekening:

citaat: tree1-> kind == tree2-> kind

Dit is geen geldige verklaring, omdat een boom knooppunt één kind heeft.

antwoordde op 12/10/2011 om 02:20
bron van user

stemmen
7

Ik denk niet dat dit een onredelijke vraag. Een eenvoudige oplossing is recursieve

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

Dit kan erg duur zijn, bijvoorbeeld in het geval wanneer we twee grote bomen soortgelijke vorm waarbij alle niet-bladknooppunten dezelfde bijbehorende waarde en bladknooppunten één een permutatie van de bladknooppunten ander.

Om voorbij dit te krijgen kun je in de eerste plaats veranderingen links en rechts als nodig, zodat links <rechts, voor sommige recursieve definitie van <. Dit kan ook duur, maar veel minder dan de controle van elke permutatie zijn, en ik denk dat een keuze van de definitie van <zou helpen. Dit zou dan kunt u om te controleren op gelijkheid met een gewone definitie.

Deze notie van http://en.wikipedia.org/wiki/Canonicalization gevolgd door gewone gelijkheid lost ook vragen op over de vraag of je echt wel een equivalentie relatie. Een equivalentie verhouding is gelijk aan een partitie. De gewone gelijkheid is natuurlijk een partitie. Als u x en y vergelijken door vergelijking f (x) en v (y), gevolgd door een equivalentierelatie nu verdeling van x en y, en dus een equivalentierelatie.

Het denken over dit, ik denk dat de weg was om te canonicalisation of maak gelijkheid-testen redelijk efficiënt is om te werken vanuit de bottom-up, annoteren elk knooppunt met een token waarvan de waarde geeft het resultaat van vergelijkingen met andere knooppunten, zodat u de knooppunten kunt vergelijken en de substructuren onder hen, gewoon vergelijken van tokens.

Dus de eerste stap naar gelijkheid is om bijvoorbeeld gebruik maken van een hash tabel om elk blad met tokens die gelijk is alleen wanneer de waarde op de bladeren zijn aan elkaar gelijk zijn aantekeningen. Dan, voor nodes wiens enige kinderen zijn bladeren, gebruik dan bijvoorbeeld een hash tabel om verder tokens toe te wijzen, zodat de tokens in die knooppunten aan elkaar gelijk zijn wanneer de bladeren, indien aanwezig, onder die knopen match. Dan kunt u gaan nog een stap omhoog, en deze keer kan je tokens vergelijken op kind knooppunten in plaats van recursief uit de boom daar. De kosten van het toekennen van tokens op deze manier moet worden lineair in de omvang van de betrokken bomen. Op de top kunt u de bomen vergelijken gewoon door het vergelijken van de penningen aan de wortel.

antwoordde op 12/10/2011 om 06:57
bron van user

stemmen
0

Ik lees de vragen als: gegeven twee binaire bomen, voor elke diepte in de boom, erachter te komen of set van hun kinderen worden behandeld in elkaar.

Dit kan worden gecodeerd relatief eenvoudig.

antwoordde op 12/10/2011 om 12:30
bron van user

stemmen
0

Oplossing zonder recursie in 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 syntax tips:

  • (1) brengen element in array: arr << elem; In dit geval for_checkwordt matrix van matrices
  • (2) parallel werkstuk: t1,t2 = [item1, item2]. Hetzelfde alsarr = [item1, item2]; t1 = arr[0]; t2 = arr[1]
  • (3) t1_children == t2_childrenveronderstelde overeenkomstige gedrag == voor dit soort voorwerpen. Meer breedsprakig zal zijn t1_children.map { |el| el.val } == t2_children.map { |el| el.val }- hier mapproduceert serie van vals.
antwoordde op 15/10/2011 om 16:17
bron van user

stemmen
1

Vergelijk bomen met behulp van heiligverklaring aanpak door gesuggereerd @mcdowella . Het verschil is dat mijn aanpak niet nodig O(N)extra geheugen mbt aantal knooppunten in de boom:

# 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()vereist O(N*M)stappen en O(log(N)*M)geheugen om alle knooppunten op in een boom, waarbij Nis totale aantal knooppunten, Maantal kinderen ieder knooppunt (het 2 binaire bomen).

canonorder()kan gemakkelijk worden gegeneraliseerd voor knooppunt representatie en elk aantal kinderen. canonwalk()vereist slechts dat een boom als een opeenvolging hebt toegang tot de directe kinderen.

De vergelijking functie die roept 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

Voorbeeld

    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)

uitgang

True
antwoordde op 15/10/2011 om 21:10
bron van user

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