Pro danou binárního stromu najít maximální binární vyhledávání sub-tree

hlasů
13

Pro danou binárního stromu, najít největší podstromu, který je také binární vyhledávací strom?

Příklad:

Vstup:

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

Výstup:

                   50
                  /   \
                 25   75
                / \   /
               15 35  65
Položena 02/07/2010 v 06:15
zdroj uživatelem
V jiných jazycích...                            


7 odpovědí

hlasů
0

Binární vyhledávací strom vám seřazený výsledek, pokud si IN-ORDER Traversal. Takže dělat traversal na zakázku pro celou binárního stromu. Nejdelší řazeny sekvence je váš největší binární vyhledávání sub strom.

  • Proveďte nezbytného traversal prvků (návštěva LEFT naleznete na ROOT, naleznete vpravo)
  • Přitom získat data uzlu porovnat, zda předchozí data uzlu je menší než další data. Pokud tomu tak je, zvýšit čítač o 1. Store start uzlu.
  • Při porovnání se nezdaří, uložte koncový uzel a obnovit čítač na 0
  • Tyto informace (counter, začátek, konec) uzel uložení v konstrukci pole později zjistit, který má maximální hodnotu, a že vám dá nejdelší binární vyhledávací strom sub
Odpovězeno 02/07/2010 v 06:26
zdroj uživatelem

hlasů
2

Zajímavá otázka!

Můj dřívější pokus byl moronically špatně!

Zde je další pokus (snad opravit tentokrát).

Jsem za předpokladu, že strom je připojen.

Předpokládejme, že pro každý uzel n stromu, jste měl soubor potomků n, s n s majetkem, který

  • Pro každého člena X S n , jedinečná cesta od n do x je binární vyhledávací strom (to je jen cesta, ale stále můžete zvážit to strom).

  • Pro každý potomek y x, tak, že se uplatní cesta od n do Y je BST, y je v S n .

Množina uzlů S n , vám dává největší BST zakořeněné v n.

Můžeme postavit S n pro každý uzel tím, že dělá prohledávání do hloubky na stromě, a předáním informace cesty (na cestě od kořene k aktuálnímu uzlu) a aktualizace sady uzlů v cestě ústupkem podél cesty.

Když jsme se navštívit uzel, chodíme po cestě, a zkontrolujte, zda je vlastnost BST je přesvědčen, že pro úsek cesty došel tak daleko. Pokud ano, přidáme aktuální uzel na odpovídající sadě uzlu cesty prostě šel do. Přestaneme chodit cestu okamžiku, kdy je nemovitost BST je porušena. Kontrola, zda segment dráhy jsme šli dosud je BST lze provést v O (1) času, na O (PATH_LENGTH) TIME Celkový čas zpracování, pro každý uzel.

Na konci, každý uzel bude mít svůj odpovídající S n naplněna. Můžeme chodit strom teď a vybrat uzel s největší hodnotou S n .

Doba potřebná k tomu je součet hloubek uzlů (v nejhorším případě), a to je O (nlogn) v průměrném případě (viz oddíl 5.2.4 http://www.toves.org/books/ Data / ch05-stromy / index.html ), ale o (n ^ 2), v nejhorším případě.

Snad chytřejší způsob, jak aktualizovat sady zaručí snížení v nejhorším případě době.

Pseudo-kód může být něco jako:

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

}
Odpovězeno 02/07/2010 v 14:13
zdroj uživatelem

hlasů
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

Jako BlueRaja zdůraznil, tento algoritmus není správné.

Mělo by být skutečně nazýván GetLargestSortedBinarySubtreeThatCanBeRecursivelyConstructedFromMaximalSortedSubtrees.

Odpovězeno 02/07/2010 v 19:46
zdroj uživatelem

hlasů
3

Předchozí algoritmus (viz revize) byl O(n^2)- můžeme zobecnit, aby O(n log n)tím všímat skutečnosti, že:

  1. V případě b je kořen největší BST a b.left.value < b.value, pak b.leftje také v BST (totéž pro b.right.value ≥ b.value)
  2. Pokud b je kořen největší BST a je také v BST, pak každý uzel mezi a a b je v BST.

Takže pokud c mezi a a b a c není v BST zakořeněné B, aniž je (vzhledem k (2)) . Používání této skutečnosti, můžeme snadno určit, zda uzel je v BST kořeny by daném předka. Budeme to tím, že projde uzlu do naší funkce, spolu se seznamem svých předchůdců, a související min / maxValues že stávající dítě uzel bude muset splňovat, pokud ovšem, že předek byl kořen největšího BST (my‘ ll nazvat tento seznam ancestorList). Budeme uložit celou sbírku potenciálních-kořenůoverallRootsList

Pojďme definovat strukturu zvanou potentialRoot takto:

Každý potentialRoot obsahuje následující hodnoty:
* uzel : Uzel uvažujeme pro kořenové BST
* MINVALUE a MAXVALUE : rozsah jiný uzel se musí nacházet mezi být součástí BST kořeny od uzlu (odlišná pro každý uzel)
* poduzly : seznam ostatních uzlů v největším BST kořeny by uzlem

Pseudo kód vypadá takto (Všimněte si, že všechny seznamy uvést seznamy 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 konci overallRootsListbude seznam npotentialRoots, z nichž každá se seznamem poduzly. Ten s největším seznamu poduzly je váš BST.

Vzhledem k tomu, existují <treeHeight hodnoty v ancestorList, pak (za předpokladu, že strom je vyvážená), algoritmus pracuje vO(n log n)

Odpovězeno 02/07/2010 v 20:21
zdroj uživatelem

hlasů
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)

Vypadá to v každém uzlu stromu právě jednou, takže běží v O (N).

Edit: Crud, to se nedomnívá, že je možné vynechat některé části podstromu. Když jsem si přečetl podstromu, předpokládal jsem, „celý strom zakořeněnou v určitém uzlu“. Mohu vrátit opravit později.

Odpovězeno 03/07/2010 v 01:15
zdroj uživatelem

hlasů
4

Tato odpověď dříve obsahoval O (n log n) algoritmus založený na link / řezaných stromů. Zde je jednodušší (n) O řešení.

Jádro je postup, který přijímá uzel, unikátní maximální BSST opatřena kořeny v jeho levé dítě, unikátní maximální BSST opatřena kořeny v jeho pravém dítěte, a odkazy na nejvíce vlevo a nejvíce vpravo prvků těchto BSSTs. Ničí jeho vstupy (kterým se lze vyhnout perzistentní datových struktur) a konstruuje odlišnou maximální BSST opatřena zakořeněného v daném uzlu, spolu s jeho minimální a maximální prvky. Všechny uzly BSST opatřena jsou komentovaný s počtem potomků. Stejně jako dříve, tento postup se nazývá opakovaně z post-objednávat traversal. Chcete-li obnovit sub-strom, pamatujte kořen největšího BSST opatřena; rekonstruuje to vyžaduje pouze jednoduché funkce traversal.

Budu léčit pouze levý BSST opatřena; vpravo je symetrická. V případě, že kořen levého BSST opatřena je větší než nová kořene, pak se celý dílčí strom se odstraní, a nový kořen je nyní nejvíce vlevo. V opačném případě se stará nejvíce vlevo uzel je stále nejvíce vlevo. Počínaje nejvíce vpravo uzlu levého BSST opatřena a pohybuje se směrem nahoru, najít první uzel, který je menší než nebo rovna kořene. Jeho pravé dítě musí být odstraněny; na vědomí, teď, že vzhledem k majetku BST, žádné jiné uzly potřebují jít! Přistoupit ke kořeni levého BSST opatřena, aktualizace počítá tak, aby odrážely vypuštění.

Důvod, proč je O (n), je to, že i přes smyčky, každá hrana v původním stromu je v podstatě prochází pouze jednou.


EDIT: kolektivně, cesty projet jsou maximální Lineární cesty v BST, s výjimkou levého páteře a na pravé páteře. Například, na vstupu

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

Zde jsou rekurzivní volání, na nichž je každá hrana prochází:

              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
Odpovězeno 03/07/2010 v 17:46
zdroj uživatelem

hlasů
1

Největší strom binárního vyhledávání v binárním stromem

Existují dva způsoby, jak můžeme tento problém přístupu,

i) Největší BST není vyvolaná (Z uzlu, všechny její děti nemusí splňovat podmínku BST)

ii) Největší BST indukované (Z uzlu, budou všechny její děti splňovat podmínku BST)

Budeme diskutovat o největší BST (nevyvolá) zde. Budeme sledovat přístup zdola nahoru (Post pořadí traversal), jak vyřešit tento.

a) Dosáhnout uzel list

b) uzel stromu (z listu) vrátí objekt TreeNodeHelper, který má následující pole v něm.

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) Původně z koncového uzlu, uzly = 1, isBST = true, MINVALUE = MAXVALUE = node.data. A dále uzly Počet se zvyšuje, pokud splňuje podmínku BST.

d) S pomocí tohoto, budeme kontrolovat stav BST s aktuálním uzlu. A budeme opakovat stejná až do kořene.

e) Z každého uzlu budou vráceny dva objekty. jeden pro poslední maximální BST a druhý pro stávající BST uspokojení uzlů. Takže z každého uzlu (nad list) (2 + 2) = 4 (2 na levém podstromu a 2 na pravém podstromu) objekty budou porovnány a dva budou vráceny.

f) konečná maximální Objekt uzlu od kořene bude největší BST

PROBLÉM:

To je problém v tomto přístupu. Zatímco budeme sledovat tento přístup, pokud podstrom, které nesplňují podmínku BST s aktuálním uzlem, nemůžeme jednoduše ignorovat podstrom (iv případě, že má menší počet uzlů). Například

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

Z koncové uzly (20110) objekty budou testovány pomocí uzlu (105), že splňuje podmínku. Ale když dosáhne uzlu (95) koncový uzel (20) nesplňuje podmínku BST. Vzhledem k tomu, je toto řešení pro BST (není indukované) neměli bychom ignorovat uzlu (105) a uzel (110), který splňuje podmínku. Takže z uzlu (95), musíme znovu ustoupit testuje stav BST a chytit ty uzly (105, 110).

Kompletní kód pro tuto realizaci je k dispozici v tomto odkazu

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

Odpovězeno 27/03/2014 v 00:48
zdroj uživatelem

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