2 binære trær er like eller ikke

stemmer
7

Mulig Duplicate:
Finn ut om to binære trær er lik

Fikk et intervju i går, et spørsmål fikk meg, her er det:

Beskrivelse

Det er 2 binary trees, sjekk om de er like.

De er like hvis og bare hvis tree1->child == tree2->child, og en treet til venstre og høyre children can be swapped with each other.

For eksempel:

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

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

Noen ideer er verdsatt.

Publisert på 12/10/2011 klokken 00:18
kilden bruker
På andre språk...                            


6 svar

stemmer
9

Likhet operatører er transitive: Hvis A = B og B = C, så er A = B = C slik at A = C.

Likestilling operatører er refleksiv: A = A, B = B, og C = C uansett hva deres verdier er.

Likestilling operatører er symmetrisk. Hvis A = B, deretter B = A. (Det spiller ingen rolle hvilken rekkefølge de er i.)

Nå, ta en titt på definisjonen de ga deg:

Et tre er lik et annet tre hvis barna er like. La oss se. Vi kan anta at nodene blir sammenlignet på bunnen, ellers definisjonen er ganske ubrukelig. Men de ikke gidder å fortelle deg hvordan du løser den sammenligningen, og hele definisjonen de ga deg hengsler på den.

Kort sagt, det er en crappy spørsmålet.

La oss se hva som skjer hvis vi bestemmer oss for vi ønsker å prøve og løse spørsmålet, skjønt.

Men vent, de også fortelle deg at de to barn i alle tre kan byttes. Dette legger begrensningen som helst tre som er lik noe annet (inkludert seg selv) må være lik sin speilbilde. Og noen varianter av sine undertrær barn blir byttet.

Og husk at dette er ment å være et søk treet. Derfor kan vi nok anta at to forskjellige søke trær som behandles av samme algoritme gi samme resultat hvis de er like. Så, hvis vi bytter rundt elementene i et tre, og søketiden ville bli berørt. Så, trær som ikke har hver node på plass er ikke lik hverandre.

Å sette det sammen med "swap" eiendom av denne likhet, kan vi se det er ikke en gyldig definisjon på likestilling. (Hvis vi prøver å bruke det, så viser det seg at bare trær som har samme node for hver node på et bestemt nivå er like, og bare til seg selv, noe som bryter refleksivitet del av en likhetsoperator.)

Svarte 12/10/2011 kl. 00:24
kilden bruker

stemmer
3

Hvis du implementerer deres definisjon av "likhet" med flip-invarians, vil du bryter definisjonen av likestilling. Definisjonen ikke selv fornuftig, fordi det er ikke hvordan binære søketrær er lik (med mindre hver node har en peker som treet er "større" og som er "mindre").

Du har to valg av fornuftige definisjoner:

  1. topologisk (flip-agnostiker) ekvivalens (i så fall kan du ikke kalle det en "binært søketre" fordi det ikke er sortert):

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

  2. normal søketreet (flipp-omsorg) ekvivalens:

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

For binære trær, vil de ovenfor angitte definisjoner fungere som skrevet i et språk som støtter listog setdatatyper (python sett vil kvele imidlertid på unhashable datatyper). Likevel, nedenfor er noen mer utførlige og stygge C / Java-lignende definisjoner:

  1. topologiske ekvivalens:

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

  2. sorterte tre ekvivalens:

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

Definisjonene ovenfor er rekursive; det vil si, de antar likestilling har blitt definert for subtreene og base-tilfeller allerede, som det har.


sidenote:

sitat: tree1-> barn == tree2-> barn

Dette er ikke en gyldig uttalelse, fordi et tre node ikke har en eneste barn.

Svarte 12/10/2011 kl. 01:20
kilden bruker

stemmer
7

Jeg tror ikke dette er en urimelig spørsmålet. En enkel løsning er rekursiv

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

Dette kan være svært kostbart, for eksempel i det tilfelle når vi har to store trær av tilsvarende form, hvor alle de ikke-bladnoder med samme pålydende verdien og bladnodene i den ene er en permutasjon av bladnodene til en annen.

For å komme forbi dette kan du først og fremst endring venstre og høyre etter behov, slik at venstre <riktig, for noen rekursiv definisjon av <. Dette kan også være dyrt, men mye mindre enn å sjekke hver permutasjon, og jeg tror et utvalg av definisjonen av <ville hjelpe. Dette vil da tillate deg å sjekke for likestilling med en vanlig definisjon.

Denne oppfatningen av http://en.wikipedia.org/wiki/Canonicalization fulgt av ordinær likeverd løser også spørsmål om hvorvidt du virkelig har en ekvivalensrelasjon. En ekvivalens forhold er ekvivalent med en skillevegg. Ordinær likestilling er åpenbart en partisjon. Hvis du sammenligner x og y ved å sammenligne f (x) og f (y) etterfulgt av en ekvivalensrelasjon du har en partisjon av x og y, og derfor en ekvivalensrelasjon.

Tenker mer om dette, tror jeg veien til å gjøre enten canonicalisation eller likestilling-testing rimelig effektiv er å jobbe fra bunnen opp, kommentere hver node med et token som har en verdi gjenspeiler resultatet av sammenligninger med andre noder, slik at du kan sammenligne noder og subtreene under dem, bare være å sammenligne tokens.

Så det første trinnet for likestilling er å f.eks bruke en hash tabell for å kommentere hvert blad med symboler som er lik bare når verdiene på bladene er like. Deretter, etter noder hvis eneste barn er bladene, bruke for eksempel en nøkkeltabell for å tilordne flere symboler, slik at spesialtegn i disse noder er lik bare når bladene, om noen, under de noder kamp. Deretter kan du gå et skritt opp, og denne gangen kan du sammenligne symboler på barnet noder i stedet for recursing ned treet der. Kostnaden med å tilordne symboler på denne måte bør være lineær i størrelsen på de involverte trærne. På toppen kan du sammenligne trær bare ved å sammenligne tokens ved roten.

Svarte 12/10/2011 kl. 05:57
kilden bruker

stemmer
0

Jeg leste spørsmålene som: gitt to binære trær, for hver dybde i treet, finne ut om barnas sett er dekket i hverandre.

Dette kan kodes relativt enkelt.

Svarte 12/10/2011 kl. 11:30
kilden bruker

stemmer
0

Løsning uten rekursjon i 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 syntaks tips:

  • (1) å sette elementet i matrisen: arr << elem; i dette tilfellet for_checker noen av matriser
  • (2) parallell tilordning: t1,t2 = [item1, item2]. Samme somarr = [item1, item2]; t1 = arr[0]; t2 = arr[1]
  • (3) t1_children == t2_childrenforutsettes tilsvarende oppførsel av == for denne type objekter. Mer detaljert vil være t1_children.map { |el| el.val } == t2_children.map { |el| el.val }- her mapproduserer rekke vals.
Svarte 15/10/2011 kl. 15:17
kilden bruker

stemmer
1

Sammenligne trær ved hjelp av kanonise tilnærming foreslått av @mcdowella . Forskjellen er at min tilnærming ikke krever O(N)ekstra minne wrt antall noder i treet:

# 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()krever O(N*M)fremgangsmåten og O(log(N)*M)hukommelse for å gi alle nodene i et tre, der Ner totalt antall noder, Mantall barn hver node har (det er 2 for binære trær).

canonorder()kan lett generaliseres til enhver node representasjon og en rekke barn. canonwalk()krever bare at et tre kan få tilgang til sine umiddelbare barn som en sekvens.

Sammenligningen funksjon som kaller 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

Eksempel

    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)

Produksjon

True
Svarte 15/10/2011 kl. 20:10
kilden bruker

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