Dla danego drzewa binarnego znaleźć maksymalną binarnego przeszukiwania poddrzewa

głosy
13

Dla danego drzewa binarnego, znaleźć największą poddrzewo które jest również binarne drzewo poszukiwań?

Przykład:

Wkład:

                   10
               /         \
             50           150
            /  \         /   \
          25    75     200    20
         / \   / \    /  \    / \
        15 35 65 30  120 135 155 250 

Wydajność:

                   50
                  /   \
                 25   75
                / \   /
               15 35  65
Utwórz 02/07/2010 o 06:15
źródło użytkownik
W innych językach...                            


7 odpowiedzi

głosy
0

Przeszukiwanie binarne drzewo daje posortowaną wynik, jeśli zrobić w prawidłowej kolejności Traversal. Więc, czy jest przechodzenie na zamówienie dla całego drzewa binarnego. Najdłuższy sortowane sekwencja jest Twój największy sub drzewo binarne wyszukiwania.

  • Zrobić przechodzenie inorder elementów (wizyta LEWO, odwiedź ROOT, przejdź w prawo)
  • Czyniąc tak, uzyskać dane węzłów, porównać, czy dane z poprzedniej węzeł jest mniejsza niż kolejnych danych. Jeśli tak, to zwiększamy licznik o 1. Store węzeł początek.
  • Gdy porównanie nie powiedzie się, należy przechowywać węzeł końcowy i wyzerować licznik do 0
  • Przechowywać te informacje (licznik, początek, koniec) węzeł w strukturze macierzy aby później dowiedzieć się, jakie jest o maksymalną wartość i że daje najdłuższy poddrzewo przeszukiwania binarnego
Odpowiedział 02/07/2010 o 06:26
źródło użytkownik

głosy
2

Interesujące pytanie!

Moja wcześniejsza próba była moronically źle!

Oto kolejna próba (mam nadzieję rozwiązać ten czas).

Jestem zakładając, że drzewo jest podłączony.

Załóżmy, że dla każdego węzła n drzewa, miałeś zestaw potomków N, S n z własności, że

  • Dla każdego członka x S n , unikalna ścieżka od n do x jest binarne drzewo poszukiwań (to jest tylko droga, ale nadal można uznać je za drzewa).

  • Dla każdego potomka y x tak, że ścieżka z n, Y jest BST y oznacza S n .

Zestaw węzłów S n , daje największą BST zakorzenione w n.

Możemy skonstruować S n dla każdego węzła, wykonując głębokość pierwszego wyszukiwania w drzewie, a przechodząc w informacji ścieżki (ścieżki od korzenia do bieżącego węzła) oraz aktualizację zestawów węzłów w ścieżce przez backtracking wzdłuż ścieżki.

Kiedy odwiedzamy węzeł, idziemy ścieżką, i sprawdzić, czy nieruchomość BST jest spełnione dla tego segmentu ścieżki podszedł do tej pory. Jeśli tak, to możemy dodać bieżący węzeł do odpowiedniego zestawu węzła drogi po prostu szliśmy do. Przestajemy spaceru ścieżką momentu nieruchomość BST jest naruszone. Sprawdzenie, czy segment ścieżki że wszedł do tej pory BST można przeprowadzić w O (1) czas do O (PATH_LENGTH) Czas całkowity czas przetwarzania dla każdego węzła.

Na koniec, każdy węzeł ma odpowiadający mu S n wypełniane. Możemy iść na drzewo i teraz wybrać węzeł z największą wartość S n .

Czas potrzebny do tego jest sumą głębi węzłów (w najgorszym przypadku), a to jest O (nlogn) w przypadku średniej (patrz punkt 5.2.4 http://www.toves.org/books/ dane / CH05 drzew / index.html ), lecz o (n ^ 2) w najgorszym przypadku.

Być może mądrzejszy sposób aktualizowania zestawów gwarantuje zmniejszenie najgorszym przypadku czas.

Pseudo-kod może być coś takiego:

static Tree void LargestBST(Tree t)
{
    LargestBST(t, new List<Pair>());
    // Walk the tree and return the largest subtree with max |S_n|.
}

static Tree LargestBST(Tree t, List<Pair> path)
{
    if (t == null) return;

    t.Set.Add(t.Value);

    int value = t.Value;
    int maxVal = value;
    int minVal = value;

    foreach (Pair p in path)
    {
        if (p.isRight)
        {
            if (minVal < p.node.Value)
            {
                break;
            }
        }

        if (!p.isRight)
        {
            if (maxVal > p.node.Value)
            {
                break;
            }
        }

        p.node.Set.Add(t.Value);

        if (p.node.Value <= minVal)
        {
            minVal = p.node.Value;
        }

        if (p.node.Value >= maxVal)
        {
            maxVal = p.node.Value;
        }
    }

    Pair pl = new Pair();
    pl.node = t;
    pl.isRight = false;

    path.Insert(0, pl);
    LargestBST(t.Left, path);

    path.RemoveAt(0);

    Pair pr = new Pair();
    pr.node = t;
    pr.isRight = true;

    path.Insert(0, pr);

    LargestBST(t.Right, path);

    path.RemoveAt(0);

}
Odpowiedział 02/07/2010 o 14:13
źródło użytkownik

głosy
0
GetLargestSortedBinarySubtree(thisNode, ref OverallBestTree)
    if thisNode == null
        Return null
    LeftLargest = GetLargestSortedBinarySubtree(thisNode.LeftNode, ref OverallBestTree)
    RightLargest = GetLargestSortedBinarySubtree(thisNode.RightNode, ref OverallBestTree)
    if LeftLargest.Max < thisNode.Value & RightLargest.Min > thisNode.Value
        currentBestTree = new BinaryTree(LeftLargest, thisNode.Value, RightLargest)
    else if LeftLargest.Max < thisNode.Value
        currentBestTree = new BinaryTree(LeftLargest, thisNode.Value, null)
    else if RightLargest.Min > thisNode.Value
        currentBestTree = new BinaryTree(null, thisNode.Value, RightLargest)
    else
        currentBestTree = new BinaryTree(null, thisNode.Value, null)
    if (currentBestTree.Size > OverallBestTree.Size)
        OverallBestTree = currentBestTree
    return currentBestTree

Jak BlueRaja wskazał, algorytm ten nie jest prawidłowy.

Powinien on być naprawdę nazywa GetLargestSortedBinarySubtreeThatCanBeRecursivelyConstructedFromMaximalSortedSubtrees.

Odpowiedział 02/07/2010 o 19:46
źródło użytkownik

głosy
3

Poprzedni algorytm (patrz wersjami) był O(n^2)- możemy generalizować go O(n log n)przez zauważać faktów:

  1. Jeśli B jest źródłem największej BST i b.left.value < b.value, a b.lefttakże w BST (również w b.right.value ≥ b.value)
  2. Jeśli b jest źródłem największego BST a także w BST, wówczas każdy węzeł między A i B jest w BST.

Więc jeśli c jest między A i B i C nie jest w BST zakorzenione B, nie jest (ze względu na (2)) . Korzystanie z tego faktu, możemy łatwo określić, czy węzeł jest w BST zakorzenione przez danego przodka. Zrobimy to poprzez przepuszczanie węzła do naszej funkcji wraz z listą jego przodkach, a wiąże się min / maxValues że obecny węzeł dzieci musiałyby spełniać, jeśli rzeczywiście, że przodek był źródłem największego BST (my” Zadzwonię do tej listy ancestorList). Będziemy przechowywać całą kolekcję potencjalnych-korzenioverallRootsList

Zdefiniujmy strukturę zwaną potentialRoot następująco:

Każdy potentialRoot zawiera następujące wartości:
* Węzeł : Węzeł rozważamy dla korzenia BST
* MINVALUE i MAXVALUE : zakres inny węzeł musi mieścić między być częścią BST zakorzenione przez węzeł (inny dla każdego węzła)
* podwęzłów : lista pozostałych węzłów w największym BST zakorzenione przez węzeł

Pseudo kod wygląda następująco (zauważ, że wszystkie listy wymienione są wykazy potentialRoots) :

FindLargestBST(node, ancestorList):
    leftList, rightList = empty lists
    for each potentialRoot in ancestorList:
        if potentialRoot.minValue < node.Value ≤ potentialRoot.maxValue:
            add node to potentialRoot.subNodes (due to (1.))
            (note that the following copies contain references, not copies, of subNodes)
            add copy of potentialRoot to leftList, setting maxValue = node.Value
            add copy of potentialRoot to rightList, setting minValue = node.Value

    add the potentialRoot (node, -∞, +∞) to leftList, rightList, and overallRootsList
    FindLargestBST(node.left, leftList)
    FindLargestBST(node.right, rightList)

Na koniec overallRootsListbędzie lista npotentialRoots, każdy z listą podwęzłów. Jedna z największych listy podwęzłów to BST.

Ponieważ istnieje <treeHeight wartości w ancestorList, następnie (zakładając, że drzewo jest zrównoważony), algorytm działa wO(n log n)

Odpowiedział 02/07/2010 o 20:21
źródło użytkownik

głosy
0
root(Tree L A R) = A

MaxBST(NULL) = (true, 0, NULL)
MaxBST(Tree L A R as T) = 
  let
    # Look at both children
    (L_is_BST, L_size, L_sub) = MaxBST(L)
    (R_is_BST, R_size, R_sub) = MaxBST(R)
  in
  # If they're both good, then this node might be good too
  if L_is_BST and R_is_BST and (L == NULL or root(L) < A) and (R == NULL or A < root(R))
  then (true, 1 + L_size + R_size, T)
  else
       # This node is no good, so give back the best our children had to offer
       (false, max(L_size, R_size), if L_size > R_size then L_sub else R_sub)

Wygląda na każdym węźle drzewa dokładnie raz, więc działa w czasie O (n).

Edit: Crud, to nie uważa, że ​​może pominąć niektóre części poddrzewa. Kiedy czytam poddrzewa, Przypuszczałem „całe drzewo zakorzenione w pewnym węźle”. Może wrócę do tego później naprawić.

Odpowiedział 03/07/2010 o 01:15
źródło użytkownik

głosy
4

Ta odpowiedź uprzednio zawarte O (n log n) algorytm oparty na link / wyciętych drzew. Tutaj jest prostsze O (n) roztworu.

Rdzeń jest procedurą, która akceptuje węzeł, unikalny maksymalny BSST zakorzenione w jej lewym dziecka, unikalny maksymalny BSST zakorzenione w jego prawej dziecka i wskazówki do większości lewej i prawej większości elementów tych BSSTs. Niszczy jego wejścia (do uniknięcia z trwałymi strukturami danych) oraz tworzy unikalny maksymalną BSST zakorzenione w danym węźle, wraz z jego minimum i maksimum elementów. Wszystkie węzły BSST są opatrzone liczbą potomków. Tak jak poprzednio, ta procedura jest wywoływana wielokrotnie z przechodzenia post-zlecenia. Aby odzyskać sub-tree, pamiętać korzeń największego BSST; rekonstrukcji wymaga jedynie prostego przechodzenie.

Będę traktować tylko lewy BSST; prawo jest symetryczna. Jeśli korzeń lewej BSST jest większa niż nowy korzeń, wówczas cała sub-tree jest usuwany, a nowy korzeń jest teraz po lewej najbardziej. W przeciwnym razie, stary węzeł lewej najbardziej pozostało-najbardziej. Zaczynając od prawej skrajnej węzła lewej BSST i przesuwając w górę, znaleźć pierwszy węzeł, który jest mniejszy lub równy korzenia. Jej tuż dziecko musi być usunięty; pamiętać, że obecnie ze względu na własności BST, żadne inne węzły trzeba iść! Przejdź do katalogu głównego lewej BSST, aktualizacji liczby w celu odzwierciedlenia skreślenia.

Powodem jest to O (n), jest to, że pomimo tej pętli każdej krawędzi w oryginalnym drzewa jest zasadniczo ruch tylko raz.


EDIT: zbiorowo, ścieżki przecinane są maksymalne ścieżki prostej linii w BST, z wyjątkiem lewego i prawego kręgosłupa kręgosłupa. Na przykład, na wejściu

              H
             / \
            /   \
           /     \
          /       \
         /         \
        /           \
       /             \
      D               L
     / \             / \
    /   \           /   \
   /     \         /     \
  B       F       J       N
 / \     / \     / \     / \
A   C   E   G   I   K   M   O

oto wywołania rekurencyjne na którym każda krawędź ciągnie się:

              H
             / \
            /   \
           /     \
          /       \
         /         \
        /           \
       /             \
      D               L
     / h             h \
    /   h           h   \
   /     h         h     \
  B       F       J       N
 / d     d h     h l     l \
A   C   E   G   I   K   M   O
Odpowiedział 03/07/2010 o 17:46
źródło użytkownik

głosy
1

NAJWIĘKSZY binarne drzewo poszukiwań w binarnym drzewa:

Istnieją dwa sposoby możemy podchodzić do tego problemu,

i) Największy BST nie indukowana (z węzła, wszystkie jego dzieci nie muszą spełniać warunek BST)

ii) Największy BST indukowana (z węzła, wszystkie jego dzieci będą spełniać warunek BST)

Będziemy dyskutować o największych BST (Nie) wywołanego tutaj. Będziemy śledzić podejście oddolne (post kolejność przejścia), aby rozwiązać ten.

a) osiąga węzeł liści

b) Węzeł drzewa (z liści) zwróci obiekt TreeNodeHelper który ma następujące pola w nim.

public static class TreeNodeHelper {
        TreeNode node;
        int nodes;
        Integer maxValue;
        Integer minValue;
        boolean isBST;


        public TreeNodeHelper() {}

        public TreeNodeHelper(TreeNode node, int nodes, Integer maxValue, Integer minValue, boolean isBST) {
            this.node = node;
            this.nodes = nodes;
            this.maxValue = maxValue;
            this.minValue = minValue;
            this.isBST = isBST;
        }      
    }

c) Początkowo od węzła liści węzły = 1, isBST = prawda MINVALUE = maxvalue = node.data. I dalej, węzły Liczba zostanie zwiększona, jeżeli spełnia warunek BST.

d) Przy pomocy tego, będziemy sprawdzać stan BST z bieżącego węzła. I będziemy powtarzać to samo do korzenia.

e) Z każdym węźle zostaną zwrócone dwa obiekty. jeden dla ostatniego maksimum BST a drugi dla aktualnych BST satysfakcjonujących węzłów. Tak więc z każdego węzła (powyżej liści) (2 + 2) = 4 (2 na lewym poddrzewie i 2 dla prawego poddrzewa) obiekty zostaną porównane i dwa będą zwracane.

f) Końcowa maksymalna węzłowi od nasady będzie największą BST

PROBLEM:

Istnieje problem w tym podejściu. A po to podejście, jeśli poddrzewo nie spełniające warunek BST z bieżącego węzła, nie możemy po prostu zignorować poddrzewo (nawet jeśli ma mniejszą liczbę węzłów). Na przykład

 55
  \
   75
  /  \
 27  89
    /  \
   26  95
      /  \
     23  105
         /  \
        20  110

Z węzłów liściowych (20110) przedmioty będą badane z węzłem (105), to spełnia warunek. Ale gdy osiągnie węzeł (95), węzeł liści (20) nie spełnia warunku BST. Ponieważ jest to rozwiązanie dla BST (nie indukowanego) nie powinniśmy ignorować węzeł (105) i węzeł (110) spełnia warunek. Więc z węzła (95) musimy wracać ponownie testuje kondycję BST i złapać tych węzłów (105, 110).

Kompletny kod dla tej implementacji jest dostępna w ten link

https://github.com/dineshappavoo/Implementation/tree/master/LARGEST_BST_IN_BT_NOT_INDUCED_VER1.0

Odpowiedział 27/03/2014 o 00:48
źródło użytkownik

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